我的知识记录

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读了,换 gbkgb18030
  • utf-8-sig 写出的文件开头多3字节BOM,给某些严格程序读时用 utf-8
  • chardet只看前10万字节,文件前面是英文、后面才是中文时可能判断不准,多读一点。

Python处理CSV编码乱码:utf-8和gbk切换方法

标签:

更新时间:2026-09-14 21:04:32

上一篇:Python CSV按列筛选导出教程:只保留需要的字段

下一篇:Python CSV去重教程:按列或整行去重保留第一条