← 中文资源

简体中文版本

Python csv — Windows 输出里多出空行

理解文本模式换行翻译导致 Windows 上 csv.writer 输出双换行的问题,并按 csv 模块要求用 newline="" 打开文件。

阅读英文原文

症状

  在任何解析器抱怨之前,症状在原始字节里就可见:od -c 显示 \r \r \n 序列——这是“翻译倍增”的指纹:csv.writer 写出的是 \r\n,文本模式文件对象又把其中的 \n 翻译成第二个 \r\n。行数佐证:同一脚本在 Windows 上产出的文件行数恰是 Linux 版的两倍;Excel 里每隔一行出现空行、pandas.read_csv 报 skipping lines 警告,都是这同一批字节的用户可见版本。

诊断思路

  先 od -c 看字节(\r\r\n 即定罪)、wc -l 对比行数;再检查喂给 csv.writer 的 open() 是否缺 newline=“”——这正是 csv 文档明确警告的组合;最后用最小循环(newline=“” 打开加 writerows)验证字节布局变为干净的 \r\n。有人为兼容 Excel 手工设置过 lineterminator、又与 open 默认翻译叠加,会把局面弄得更乱,先清掉手工设置再统一按文档来。

根因

  csv 模块自己管理行终止并写出 \r\n;默认文本模式打开的文件在 Windows 上把每个 \n 再次翻译为 \r\n,于是每行以 \r\r\n 收尾,读者在数据行之间看到空行。

修复与验证

  写 CSV 一律用 open(path, “w”, newline=“”, encoding=“utf-8”),把字节级行尾的所有权完全交给 csv 模块;在内存里拼 CSV 字符串时用 io.StringIO(newline=“”),理由相同;读方向同样要求 newline=“”——含引号内嵌换行的字段只有在禁用行分割后才完整。验证时在 Windows 上写一个含多行字段的夹具,od 断言行尾字节精确为 \r\n,再用 csv.reader 与 pandas.read_csv 往返读回,零警告零跳行。

代码示例

$ od -c out.csv | head -3
0000000   i   d   ,   n   a   m   e   \r  \r  \n   1   ,   a   \r  \r  \n
import csv

with open("out.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["id", "name"])
    writer.writerows(rows)
# byte endings are now exactly \r\n — csv owns them
import io

buf = io.StringIO(newline="")
csv.writer(buf).writerows(rows)
payload = buf.getvalue()