应使用encoding='utf-8-sig'打开文件,它会自动剥离utf-8 bom(\xef\xbb\xbf),避免开头出现或解析失败;该编码对无bom文件完全兼容,无需手动判断或切片。

Python打开UTF-8 BOM文件时中文乱码怎么办
直接用 open('file.txt', encoding='utf-8') 读取带BOM的文件,通常不会出错——但如果你看到开头多出  或解析JSON/XML失败、正则匹配偏移,大概率是BOM没被正确剥离。Python的 utf-8 编码器本身不自动跳过BOM,它会把BOM当普通字符解码进字符串。
用 utf-8-sig 编码自动处理BOM
utf-8-sig 是Python内置的变体编码,读取时自动检测并剥离UTF-8 BOM(\xef\xbb\xbf),写入时默认在开头添加BOM(除非显式禁用)。这是最省心、最推荐的做法。
实操建议:
- 读文件一律改用
encoding='utf-8-sig',无需额外判断或切片 - 写文件若需兼容旧系统(如某些Windows记事本),保留
utf-8-sig;若明确不要BOM(如Web API响应、JSON输出),改用utf-8 - 注意:BOM只影响首次读取,后续对字符串操作与普通UTF-8无异
with open('data.csv', encoding='utf-8-sig') as f:
content = f.read() # BOM已消失,content[0] 就是真实首字符
手动剥离BOM的适用场景和风险
仅在无法修改 open() 参数(如第三方库强制指定encoding)或需要细粒度控制时才手动处理。容易踩的坑包括:
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
- 误判BOM:只检查前3字节是否为
\xef\xbb\xbf,但文件可能根本不是UTF-8(比如是GBK) - 重复剥离:用
utf-8-sig读完再调.lstrip('\ufeff'),反而可能删掉用户本来想保留的零宽空格 - 二进制模式下忘记decode:用
rb模式读取后,必须先.decode('utf-8')才能用字符串方法处理
安全的手动方式(仅限必需时):
with open('log.txt', 'rb') as f:
raw = f.read()
if raw.startswith(b'\xef\xbb\xbf'):
content = raw[3:].decode('utf-8')
else:
content = raw.decode('utf-8')
为什么不用 chardet 或 charset_normalizer 检测BOM
BOM是编码标识的一部分,不是独立的“字符集”,靠统计分析的检测库(如 chardet)对BOM识别不稳定,且引入额外依赖和延迟。它们更适合处理**完全未知编码**的文件,而BOM本身已是明确的UTF-8信号——你已经知道它是UTF-8,只是多了个头。
真正要注意的是:有些编辑器(如VS Code)保存时默认加BOM,有些(如Linux vim)默认不加。如果文件由多人协作生成,统一用 utf-8-sig 读取比到处加检测逻辑更可靠。
BOM不是bug,是历史包袱;处理它的最好方式,就是让Python替你默默吞掉它。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










