为什么Python的open()函数读取UTF-8文件时会出现字符乱码?
问题核心原因
这个现象本质是打印输出阶段的终端编码不匹配,和open()读取文件的逻辑无关,你碰到的假正常/乱码的逻辑是:
- 用
utf-8-sig读取时,文件内容被正确解码为Unicode字符串存在内存中,但打印时Python会将字符串按终端默认编码(Windows下默认是对应系统区域的ANSI编码,中文系统为GBK)转码后输出,UTF-8的非ANSI字符转GBK时出错,就显示乱码。 - 用
ansi读取时,你是把UTF-8编码的二进制内容错误按ANSI规则解码,内存里的字符串本身是错的,但这个错误解码的字符串转码回ANSI输出到终端时,刚好抵消了解码的错误,显示出来就看起来正常,这也是为什么Lark库会报错——它拿到的内容本身就是解码错误的字符串。
排查验证方法
你可以通过两个操作确认问题来源:
- 不要直接打印读取结果,执行
print(repr(grammar.read()))查看输出的Unicode码点是否和你预期的字符对应,如果码点正确,说明读取阶段完全没有问题。 - 将
utf-8-sig读取的内容写入新文件:
with open("test_output.txt", "w", encoding="utf-8") as f: f.write(grammar.read())
打开新文件查看内容如果完全正常,就可以100%确认是终端输出环节的问题。
常见触发原因&解决方案
如果确认是输出环节问题,大概率是Python版本更新后调整了终端编码的检测逻辑,或者终端默认编码被修改,可通过以下方案解决:
- 临时方案:运行代码前在终端执行
chcp 65001,将当前终端的代码页切换为UTF-8,再运行代码即可正常显示。 - 永久方案:设置系统环境变量
PYTHONUTF8=1,强制Python所有标准输入输出都使用UTF-8编码,不受终端默认编码影响。 - 如果你是在Windows上运行,也可以直接使用Windows Terminal替代默认的cmd/powershell,它默认使用UTF-8编码,不会出现该类乱码问题。
内容的提问来源于stack exchange,提问作者algorev
相关产品推荐
相关产品推荐

