本文介绍如何用纯python代码安全、高效地替代shell中awk命令实现“按首字段去重”功能,彻底规避subprocess.run调用awk时因文本/字节模式不匹配导致的typeerror。
在Python项目中,为实现类似 awk -F, ‘!seen[$1]++’(即按CSV首列去重并保留首次出现行)的功能而调用外部awk命令,不仅引入不必要的进程开销和平台依赖,还极易因I/O模式不一致引发运行时异常——例如你遇到的:
TypeError: expected str, bytes, or os.PathLike object, not _io.TextIOWrapper
该错误的根本原因在于:subprocess.run(…, stdout=open(ndfile, ‘w’)) 中,stdout 接收的是子进程输出的字节流(默认行为),但 open(ndfile, ‘w’) 返回的是文本模式文件对象,二者类型不兼容。虽然可通过添加 text=True 参数强制 subprocess 以文本模式通信,或改用 ‘wb’ 模式打开文件来临时修复,但这只是治标;真正健壮、可维护、跨平台的解法是——用原生Python重写逻辑。
以下为推荐的纯Python实现,兼具清晰性、效率与鲁棒性:
with open(filename, "r", encoding="utf-8") as infile, \
open(ndfile, "w", encoding="utf-8") as outfile:
seen = set()
for line in infile:
# 安全提取首字段:去除行尾换行符后按逗号分割,取第0项
key = line.rstrip("\r\n").split(",", 1)[0] # 使用 split(..., 1) 提升大文件性能
if key not in seen:
seen.add(key)
outfile.write(line)
✅ 关键优化说明: