Python文本乱码根本原因和解决方案

 更新时间:2026年02月15日 08:29:41   作者:detayun  
乱码是每个Python开发者,尤其是处理中文、日文等非ASCII字符时,都会遇到的噩梦,这篇文章将带你彻底理解乱码产生的根本原因,并提供一套行之有效的解决方案和最佳实践,需要的朋友可以参考下

“乱码”是每个Python开发者,尤其是处理中文、日文等非ASCII字符时,都会遇到的“噩梦”。明明代码逻辑正确,文件也存在,但打印出来或保存的文件却是一堆莫名其妙的符号(如éÂ\x87Â\x91éÂ\x9eÂ\x93)。

这篇文章将带你彻底理解乱码产生的根本原因,并提供一套行之有效的解决方案和最佳实践。

一、乱码的本质:编码与解码的“鸡同鸭讲”

要理解乱码,首先必须明白两个核心概念:字符集(Charset)字符编码(Character Encoding)

字符集(Charset):是一个系统支持的所有抽象字符的集合。比如:

  • ASCII:包含128个字符(英文字母、数字、符号),用1个字节(8位)表示。
  • GBK/GB2312:中国国家标准,包含汉字、符号等,用1或2个字节表示。
  • Unicode:一个超级字符集,包含了世界上几乎所有语言的字符。它本身不是编码,而是编码的基础

字符编码(Encoding):是将字符集中的字符映射为二进制数据(字节)的规则。Unicode字符集有多种实现编码:

  • UTF-8:变长编码(1-4字节),兼容ASCII,是互联网的事实标准。
  • UTF-16:固定2或4字节。
  • UTF-32:固定4字节。

乱码产生的根本原因编码和解码时使用了不同的规则

(想象一个流程图:字符 -> [编码] -> 字节 -> [解码] -> 字符。如果编码和解码的规则不一致,就会得到错误的字符)

举个例子
汉字“金”的Unicode码点是 U+91D1

  • UTF-8 编码后,字节序列是:0xE9 0x87 0x91
  • GBK 编码后,字节序列是:0xBD 0xF0

如果你用UTF-8编码了“金”,得到 0xE9 0x87 0x91,但却错误地用GBK去解码它,GBK会认为 0xE9 是一个汉字的第一个字节,并尝试寻找第二个字节,最终组合成一个完全不同的、甚至无效的字符,这就是乱码。

二、Python中的乱码重灾区与解决方案

Python 3在内存中统一使用Unicode(准确说是UCS-4/UTF-32的子集)来表示字符串,这大大减少了内存中的乱码问题。乱码主要发生在“输入/输出”环节,即字节流(bytes)和字符串(str)转换的边界

场景1:文件读写(最常见!)

错误示范

# 写入文件时未指定编码(使用系统默认编码,Windows下通常是GBK)
with open('test.txt', 'w') as f:
    f.write('金') # 内存中的Unicode '金' 被用系统编码(如GBK)转换为字节写入

# 读取文件时也未指定编码
with open('test.txt', 'r') as f:
    content = f.read() # 文件中的GBK字节被用系统编码(如GBK)解码回Unicode,如果系统编码变了或文件是UTF-8,就会乱码

正确做法:始终显式指定编码(推荐UTF-8)

# 写入
with open('test.txt', 'w', encoding='utf-8') as f:
    f.write('金') # 明确用UTF-8编码

# 读取
with open('test.txt', 'r', encoding='utf-8') as f:
    content = f.read() # 明确用UTF-8解码

黄金法则:在打开文件时,永远加上 encoding='utf-8' 参数。

场景2:网络请求(如requests库)

网页服务器会在HTTP响应头中通过 Content-Type 字段声明编码(如 charset=gb2312)。requests 库会自动猜测编码,但有时会猜错。

错误示范

import requests
response = requests.get('http://example.com')
print(response.text) # requests库自动猜测编码,可能猜错导致乱码

正确做法:手动修正编码

import requests
response = requests.get('http://example.com')

# 方法1:直接修改编码属性(推荐)
response.encoding = 'utf-8' # 或者 'gbk', 'gb2312' 等,根据网页源码判断
print(response.text)

# 方法2:使用内容自动检测(需要chardet库)
import chardet
detected_encoding = chardet.detect(response.content)['encoding']
response.encoding = detected_encoding
print(response.text)

场景3:终端/控制台输出

Python脚本在终端(CMD、PowerShell、Bash)中打印中文时出现乱码,通常是因为终端的编码与Python输出的编码不一致。

  • Windows CMD:默认编码是GBK(代码页936)。
  • 现代终端(Windows Terminal, VS Code终端):通常支持UTF-8。

解决方案

  1. 统一终端编码为UTF-8(推荐):
    • 在Windows CMD中执行:chcp 65001 (切换代码页到UTF-8)
    • 在PowerShell中:$OutputEncoding = [System.Text.Encoding]::UTF8
  2. 在Python脚本中适配(不推荐,治标不治本):
import sys
import io
# 强制将stdout的编码改为UTF-8
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
print('金')

场景4:Python源码文件本身的编码

如果你的 .py 文件中包含中文字符串(如注释、字符串字面量),并且文件保存时用的编码(如GBK)与Python解释器读取时用的编码(默认UTF-8)不一致,会导致 SyntaxError 或乱码。

解决方案

  1. 在文件开头添加编码声明(Python2必需,Python3推荐):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
  1. 确保你的代码编辑器(如VSCode, PyCharm)将文件保存为UTF-8编码。这是最根本的解决方法。

三、排查乱码的神器

chardet:检测未知字节数据的编码。

pip install chardet
import chardet
with open('unknown_encoding.txt', 'rb') as f: # 注意用'rb'二进制模式读取
    raw_data = f.read()
    result = chardet.detect(raw_data)
    print(result) # 输出:{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}

在线编码转换工具:如 Base64/Hex/UTF-8转换工具,可以手动粘贴字节流进行转换测试。

四、总结与最佳实践

  1. 黄金法则显式优于隐式。在任何涉及字节流和字符串转换的地方(文件、网络、数据库),都明确指定编码,首选 utf-8
  2. 统一标准:整个项目(源码文件、数据文件、数据库、网页)尽量统一使用 UTF-8 编码,从根源上避免转换错误。
  3. 理解流程:时刻清醒地认识到数据在“内存(Unicode)”和“外部(字节流)”之间的转换过程,确保两端使用相同的“密码本”(编码)。
  4. 使用二进制模式:当你不确定编码,或者需要处理原始字节时,先用 'rb' 模式读取文件,得到 bytes 对象后再进行解码。

遵循以上原则,你就能告别乱码烦恼,让你的Python程序在处理多语言文本时游刃有余。记住,乱码不是Bug,而是编码和解码规则不匹配的必然结果——解决它的关键就在于明确规则

以上就是Python文本乱码根本原因和解决方案的详细内容,更多关于Python文本乱码原因和解决的资料请关注脚本之家其它相关文章!

相关文章

  • Python实现字典序列ChainMap

    Python实现字典序列ChainMap

    容器数据类型包括数组list,字典dict以及元组tuple等。本篇主要介绍了ChainMap字典序列的使用,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • Numpy中转置transpose、T和swapaxes的实例讲解

    Numpy中转置transpose、T和swapaxes的实例讲解

    下面小编就为大家分享一篇Numpy中转置transpose、T和swapaxes的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-04-04
  • python docx的超链接网址和链接文本操作

    python docx的超链接网址和链接文本操作

    这篇文章主要介绍了python docx的超链接网址和链接文本操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • python远程调用rpc模块xmlrpclib的方法

    python远程调用rpc模块xmlrpclib的方法

    今天小编就为大家分享一篇python远程调用rpc模块xmlrpclib的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-01-01
  • Python自动化办公之Excel数据的写入

    Python自动化办公之Excel数据的写入

    这篇文章主要为大家详细介绍一下Python中excel的写入模块- xlsxwriter,并利用该模块实现Excel数据的写入,感兴趣的小伙伴可以了解一下
    2022-05-05
  • 关于pycharm 切换 python3.9 报错 ‘HTMLParser‘ object has no attribute ‘unescape‘ 的问题

    关于pycharm 切换 python3.9 报错 ‘HTMLParser‘ object has no attribu

    这篇文章主要介绍了pycharm 切换 python3.9 报错 ‘HTMLParser‘ object has no attribute ‘unescape‘ 解决,需要的朋友可以参考下
    2020-11-11
  • 使用Python通过oBIX协议访问Niagara数据的示例

    使用Python通过oBIX协议访问Niagara数据的示例

    这篇文章主要介绍了使用Python通过oBIX协议访问Niagara数据的示例,帮助大家更好的理解和学习python,感兴趣的朋友可以了解下
    2020-12-12
  • Python中的循环语句详细代码示例

    Python中的循环语句详细代码示例

    Python是一种通用且功能强大的编程语言,它提供了各种结构来有效地处理重复性任务,循环概念就是这方面的基本工具之一,这篇文章主要介绍了Python中循环语句的相关资料,需要的朋友可以参考下
    2026-01-01
  • python求解汉诺塔游戏

    python求解汉诺塔游戏

    这篇文章主要为大家详细介绍了python求解汉诺塔游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • python opencv 画外接矩形框的完整代码

    python opencv 画外接矩形框的完整代码

    这篇文章主要介绍了python-opencv-画外接矩形框的实例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09

最新评论