应先用chardet探测实际编码,再传给pandas的encoding参数;常见编码为gbk(Windows中文CSV)、utf-8-sig(带BOM的UTF-8)和latin-1(兜底),需注意BOM、大小写及分隔符识别问题。

读CSV时报UnicodeDecodeError:怎么选对encoding
乱码本质是编码声明和实际字节不匹配。Pandas默认用utf-8解码,但Windows记事本保存的中文CSV常是gbk或gb2312,Linux/macOS下可能混着utf-8-sig(带BOM)。别猜,先试chardet查:
import chardet
with open('data.csv', 'rb') as f:
print(chardet.detect(f.read(10000)))
输出类似{'encoding': 'gbk', 'confidence': 0.99}就信它。常见组合:
-
gbk:国内大多数Excel/记事本导出的中文CSV -
utf-8-sig:VS Code或某些Python脚本生成的UTF-8文件(开头有BOM) -
latin-1:当其他都失败时兜底(不会报错,但中文变乱码字符,可辅助判断是否真为GBK)
pd.read_csv()里encoding参数填什么才不报错
直接把chardet结果里的encoding值塞进encoding参数就行。注意几个易错点:
- 别写成
encoding='UTF-8'——大小写不敏感,但utf-8更稳妥 -
utf-8-sig必须显式写全,不能只写utf-8,否则BOM残留会导致首列名多出ufeff - 如果文件由Excel另存为“CSV UTF-8”,实际是
utf-8-sig,不是纯utf-8 - Mac上用Numbers导出的CSV有时是
mac-roman,极少见但得留心
正确示例:
df = pd.read_csv('data.csv', encoding='gbk')
# 或
df = pd.read_csv('data.csv', encoding='utf-8-sig')
读进来还是乱码?检查sep和encoding是否打架
有些CSV用中文逗号、分号甚至制表符分隔,但encoding错了会导致sep识别失效——比如gbk错用utf-8读,一个中文逗号被拆成两个无效字节,Pandas就找不到分隔符,整行当一列。
- 先用文本编辑器(如Notepad++、VS Code)以目标编码重新打开文件,确认分隔符确实是英文逗号
- 若分隔符是中文逗号,加
sep=','(注意是中文字符) - 若列名本身含逗号(如“用户,姓名”),必须加
quotechar='"'并确保原始文件用了双引号包裹字段 - Windows路径中反斜杠
在Python字符串里要写成\或用原始字符串r'C:data.csv'
批量处理多个CSV时如何自动适配编码
不能每次手动跑chardet。简单可靠的做法是写个探测函数,按优先级尝试常见编码:
def read_csv_auto(path):
for enc in ['utf-8-sig', 'gbk', 'utf-8', 'latin-1']:
try:
return pd.read_csv(path, encoding=enc)
except UnicodeDecodeError:
continue
raise ValueError(f'Cannot decode {path} with any known encoding')
这个策略够用,但要注意:
-
latin-1永远不抛错,所以放最后;排太前会掩盖真实编码问题 - 文件很大时,
chardet只读前1万字节,但实际编码可能在后面变化(极罕见,多见于拼接文件) - 如果同一目录下文件编码不一致,必须单个处理,没法统一设一个
encoding
最麻烦的情况其实是:CSV里混了多种编码——比如从不同系统导出再合并的文件。这种没银弹,得先清洗源数据。










