用 utf-8-sig 编码写入 CSV 可解决 Windows Excel 打开中文乱码问题,因其自动添加 BOM(\ufeff)使 Excel 正确识别 UTF-8;需在 open() 中显式指定 encoding='utf-8-sig',csv.writer 不处理编码。

用 utf-8-sig 编码写入 CSV 就能避免 Excel 打开乱码
Excel(尤其是 Windows 版)默认把纯 UTF-8 当作系统本地编码(如 GBK),导致中文变问号或方块。加 BOM 是最简单、兼容性最好的解法,而 Python 的 utf-8-sig 编码会自动在开头写入 \ufeff,且读取时自动忽略它——不用手动拼接、也不用担心多出字符。
常见错误现象:open(..., encoding='utf-8') 写出的 CSV 在 Excel 里显示“涓枃”;用记事本另存为“UTF-8-BOM”再打开才正常;或者改用 cp936 虽然能看,但跨平台就崩。
- 只对写入文本文件有效(
csv.writer、file.write()等),print()或日志库不走这个路径 -
utf-8-sig和utf-8读取行为一致,但写入时前者加 BOM,后者不加 - macOS/Linux 的 LibreOffice 或 WPS 通常不依赖 BOM,但 Windows Excel 必须靠它识别 UTF-8
csv.writer 写入必须显式指定 encoding='utf-8-sig'
很多人以为 csv.writer 自动处理编码,其实它只管分隔和转义,底层文件对象的编码才是关键。漏掉 encoding 参数或写成 'utf-8',BOM 就不会出现。
使用场景:导出报表、数据清洗后保存为 Excel 可读的 CSV。
立即学习“Python免费学习笔记(深入)”;
- 正确写法:
with open('data.csv', 'w', encoding='utf-8-sig') as f:→csv.writer(f) - 错误写法:
with open('data.csv', 'w', encoding='utf-8')(没 BOM)、with open('data.csv', 'wb')(二进制模式,csv.writer会报错) - 如果用
pandas.to_csv(),直接传encoding='utf-8-sig'即可,它内部已适配
别用 codecs 或手动写 BOM —— 多余且易出错
有人查到要先写 b'\xef\xbb\xbf',然后用 codecs.open(..., 'w', 'utf-8'),这既绕路又危险:BOM 可能被重复写入,或在追加模式下插到中间,破坏 CSV 结构。
性能与兼容性影响:手动操作增加出错概率,且 codecs 模块在 Python 3 中基本被内置 open() 取代;utf-8-sig 是标准编码名,所有 Python 3.3+ 都支持,无额外依赖。
- 绝对不要:
f.write('\ufeff')+encoding='utf-8'(BOM 和内容编码不匹配,可能触发异常) - 也别用:
codecs.open(..., 'w', 'utf-8-sig')(多余,open()原生支持) - 验证是否生效:用十六进制编辑器(如 VS Code 的 Hex Editor 扩展)打开 CSV,前三个字节应是
ef bb bf
Windows 记事本不是可靠验证工具
记事本保存为“UTF-8”时,实际写的是带 BOM 的 UTF-8,但它自己读的时候又会隐藏 BOM,导致你以为“没 BOM 也能正常”,其实是记事本做了特殊处理。Excel 不会这样宽容。
容易被忽略的地方:BOM 只解决“编码识别”问题,不解决字段内换行、逗号、引号转义等 CSV 格式问题;如果数据本身含 \r\n 且没被 csv.writer 正确包裹,Excel 仍可能错行。
真正需要检查的,是 Excel 打开后的第一眼——中文是否可读、列是否对齐、有没有意外空行。别的都只是中间环节。










