Python处理CSV编码乱码:utf-8和gbk切换方法
解决Python读取CSV中文乱码问题,对比utf-8、utf-8-sig、gbk、gb18030几种编码,给出自动探测和转码方法,附完整代码。
场景痛点
用pandas或csv打开别人发的CSV,表头变成 测试 或者 锟斤拷;自己写的CSV发给同事,对方Excel打开一片乱码。中文CSV编码坑太多:Excel默认存GBK,Linux服务器默认UTF-8,跨系统传输必乱。这篇把常用编码和自动探测方法讲清楚。
用到的库
pip install pandas chardet
完整代码
# Python处理CSV编码乱码
import pandas as pd
def try_read_with_encodings(file_path):
"""
按顺序尝试几种常见编码,哪个能读出来就用哪个。
常见顺序:utf-8-sig -> gbk -> gb18030 -> utf-8
"""
encodings = ["utf-8-sig", "gbk", "gb18030", "utf-8", "latin1"]
for enc in encodings:
try:
df = pd.read_csv(file_path, encoding=enc, nrows=5)
print(f"成功用编码 {enc} 读取,前5行:")
print(df.head())
return enc, df
except (UnicodeDecodeError, UnicodeError):
print(f" 编码 {enc} 失败,换下一个")
raise RuntimeError("所有编码都读不了,请用chardet探测")
def detect_encoding(file_path):
"""
用chardet自动探测文件真实编码,适合不确定来源的CSV。
只读前1万字节判断,速度快。
"""
import chardet
with open(file_path, "rb") as f:
raw = f.read(100000) # 读前10万字节
result = chardet.detect(raw)
print(f"chardet探测结果:{result}")
return result["encoding"]
def convert_to_utf8(input_path, output_path):
"""
把任意编码的CSV转成统一的utf-8-sig,后续程序读起来就不会乱码。
"""
enc = detect_encoding(input_path)
df = pd.read_csv(input_path, encoding=enc)
# 写出用utf-8-sig,Excel双击也能正常打开
df.to_csv(output_path, index=False, encoding="utf-8-sig")
print(f"已转码:{input_path}({enc}) -> {output_path}(utf-8-sig)")
def main():
file_path = "messy.csv"
print("=== 1. 逐个编码尝试读取 ===")
enc, df = try_read_with_encodings(file_path)
print("\n=== 2. chardet自动探测 ===")
detect_encoding(file_path)
print("\n=== 3. 统一转成utf-8-sig ===")
convert_to_utf8(file_path, "clean_utf8.csv")
if __name__ == "__main__":
main()
代码讲解
utf-8-sig是带BOM的UTF-8,能兼容Excel双击打开,也是最推荐的读取编码。gbk是Windows中文版默认编码,gb18030是GBK超集,能读一些生僻字。latin1是兜底,任何字节都能读出来,但中文会变成乱码,只用于探测失败时强行读。chardet.detect读文件头部字节,根据统计猜出编码,准确率够用。- 统一转成
utf-8-sig后存一份,后面所有脚本都用这个编码,一劳永逸。
运行结果
控制台先逐个尝试编码,打印哪个成功了;再用chardet给出探测结果;最后生成一份干净的 clean_utf8.csv,以后读这个文件永远不用纠结编码。
注意事项
- 乱码成
测试这种是UTF-8被当Latin1读了,加encoding="utf-8"就行。 - 乱码成
娴嬭瘯这种是GBK被当UTF-8读了,换gbk或gb18030。 utf-8-sig写出的文件开头多3字节BOM,给某些严格程序读时用utf-8。- chardet只看前10万字节,文件前面是英文、后面才是中文时可能判断不准,多读一点。

更新时间:2026-09-14 21:04:32
上一篇:Python CSV按列筛选导出教程:只保留需要的字段