根本原因是文件实际编码与Python默认解码编码不匹配;open()未指定encoding时,Python 3依据locale.getpreferredencoding()猜测编码,中文Windows默认为'gbk',Linux/macOS默认为'utf-8'。

UnicodeDecodeError 出现的根本原因,是 Python 试图用一种编码方式去解释字节序列,但该字节序列根本不是按那种方式编码出来的——就像拿英文词典查中文笔画,必然查不到。
open() 不指定 encoding 时到底用了什么?
- Python 3 的
open()在文本模式('r'、'w')下必须解码字节为str,所以它得猜一个编码。 - 这个“猜”的依据是:
locale.getpreferredencoding(),在中文 Windows 上通常是'gbk';Linux/macOS 上通常是'utf-8'。 - 所以同一段代码:
with open('data.txt', 'r') as f: f.read()在同事的 macOS 上跑通,在你的 Windows 上报
UnicodeDecodeError: 'gbk' codec can't decode byte 0xad...——不是代码有问题,是默认编码不同。
文件实际编码和你指定的 encoding 不匹配的典型表现
- 用记事本保存为「ANSI」(即 GBK),却用
encoding='utf-8'去读 → 报UnicodeDecodeError: 'utf-8' codec can't decode byte 0xce in position 0: invalid continuation byte - 文件是 UTF-8(无 BOM),却用
encoding='gbk'去读 → 报UnicodeDecodeError: 'gbk' codec can't decode byte 0xa5 in position 5: illegal multibyte sequence - 文件是 UTF-8 with BOM,用
encoding='utf-8'读出来开头多一个'\ufeff'→ 后续 JSON 解析或字符串比较失败
怎么选对 encoding?优先级要清楚
- 明确知道来源:Web API 返回、Linux 生成的日志、VS Code 新建的文件 → 默认信
'utf-8' - Windows 上双击能正常打开的记事本文件 → 先试
'gbk',再试'gb18030'(兼容性更好) - 怀疑有 BOM 的 UTF-8 文件 → 改用
'utf-8-sig',它会自动剥离 BOM,不会污染内容 - 完全不确定 → 不要硬猜,先用
chardet探测:import chardet with open('data.txt', 'rb') as f: raw = f.read(10000) # 只读前 10KB 足够判断 enc = chardet.detect(raw)['encoding'] # 可能返回 'GBK', 'UTF-8', None
encoding 参数不是可选项,而是责任声明。你写上它,就等于告诉 Python:“我确认这串字节是按这个规则打包的”。漏掉它,就是在让解释器替你赌一把——而乱码,就是输掉的代价。


















