codecs.open()比内置open()更可控,因其强制指定encoding且errors行为更可预测;Python 3内置open()默认UTF-8,遇GBK等编码易抛UnicodeDecodeError,且部分老旧编码支持不稳定。

直接用 codecs.open() 读写非UTF-8文件,比内置 open() 更可控,尤其在 Python 3.6 之前或需要显式指定错误处理策略时。
为什么不能只靠内置 open()?
Python 3 的内置 open() 默认用 UTF-8 解码,遇到 GBK、Shift-JIS 或 ISO-8859-1 文件会直接抛 UnicodeDecodeError。虽然它也支持 encoding 参数,但某些老旧编码(如 gb2312)在部分系统上可能缺失或行为不一致;codecs 模块对编码注册更宽松,且提供更细粒度的 errors 控制。
codecs.open() 的核心参数怎么配?
codecs.open() 接口和内置 open() 几乎一致,但必须显式传 encoding,且 errors 行为更可预测:
-
encoding:填编码名字符串,如"gbk"、"shift_jis"、"iso-8859-1"(注意不是"latin-1"—— 虽然等价,但某些环境认前者更稳) -
errors:推荐用"replace"(替换为 )或"ignore"(跳过非法字节),避免程序中断;"strict"是默认值,但容易崩 - 不要混用
codecs.open()和io.TextIOWrapper套接 —— 容易双重解码导致乱码
示例:读取一个 GBK 编码的 log 文件
立即学习“Python免费学习笔记(深入)”;
import codecs
with codecs.open("app.log", "r", encoding="gbk", errors="replace") as f:
content = f.read()
写文件时编码转换容易出什么错?
写入非 UTF-8 文件时,常见问题不是读不出来,而是「写进去的内容被其他程序读错」—— 因为没写 BOM 或编码声明:
- GBK/GB2312 文件一般不带 BOM,但若用
encoding="utf-8-sig"写,再用 GBK 读就会多出乱码头 - 写
shift_jis文件后,Windows 记事本可能默认用 UTF-8 打开,显示全乱 —— 这不是代码错,是编辑器没识别编码 -
codecs.open(..., "w")不会自动追加 BOM,要手动写:比如写 UTF-16 就得先f.write("\ufeff")
安全写法示例(覆盖写 GBK 文件):
import codecs
with codecs.open("output.txt", "w", encoding="gbk", errors="ignore") as f:
f.write("你好,世界!")
Python 3.7+ 是否还该用 codecs?
多数场景下,内置 open() 已足够:它底层就调用了 codecs,且编码支持更全(如新增了 "cp949")。但以下情况仍需 codecs:
- 需要
codecs.register_error()自定义错误处理器(比如把乱码转成拼音) - 用
codecs.EncodedFile()做运行时编码转换(少见,但某些流式处理绕不开) - 兼容旧项目中大量
codecs.open()调用,且不想改逻辑
真正麻烦的从来不是选哪个模块,而是搞不清文件原始编码 —— 用 chardet 或 charset-normalizer 先探测,别靠猜。


















