跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python

Python 文本乱码原因及解决方案

Python 文本乱码主要由字符集与编码规则不一致引起,常见于文件读写、网络请求及终端输出环节。解决核心在于显式指定 UTF-8 编码,统一项目标准,并理解内存 Unicode 与外部字节流的转换过程。通过 chardet 库检测或手动修正 encoding 属性可有效排查问题。

怪力乱神发布于 2026/3/16更新于 2026/6/1637 浏览

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

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

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

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

  1. 字符集(Charset):是一个系统支持的所有抽象字符的集合。比如:
    • ASCII:包含 128 个字符(英文字母、数字、符号),用 1 个字节(8 位)表示。
    • GBK/GB2312:中国国家标准,包含汉字、符号等,用 1 或 2 个字节表示。
    • Unicode:一个超级字符集,包含了世界上几乎所有语言的字符。它本身不是编码,而是编码的基础。
  2. 字符编码(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

在 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. 确保你的代码编辑器(如 VSCode, PyCharm)将文件保存为 UTF-8 编码。这是最根本的解决方法。

在文件开头添加编码声明(Python2 必需,Python3 推荐):

#!/usr/bin/env python
# -*- coding: utf-8 -*-

三、排查乱码的神器

  1. 在线编码转换工具:如 Base64/Hex/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': ''}

四、总结与最佳实践

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

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

目录

  1. 一、乱码的本质:编码与解码的“鸡同鸭讲”
  2. 二、Python 中的乱码重灾区与解决方案
  3. 场景 1:文件读写(最常见!)
  4. 写入文件时未指定编码(使用系统默认编码,Windows 下通常是 GBK)
  5. 内存中的 Unicode '金' 被用系统编码(如 GBK)转换为字节写入
  6. 读取文件时也未指定编码
  7. 文件中的 GBK 字节被用系统编码(如 GBK)解码回 Unicode,如果系统编码变了或文件是 UTF-8,就会乱码
  8. 写入
  9. 明确用 UTF-8 编码
  10. 读取
  11. 明确用 UTF-8 解码
  12. 场景 2:网络请求(如 requests 库)
  13. requests 库自动猜测编码,可能猜错导致乱码
  14. 方法 1:直接修改编码属性(推荐)
  15. 或者 'gbk', 'gb2312' 等,根据网页源码判断
  16. 方法 2:使用内容自动检测(需要 chardet 库)
  17. 场景 3:终端/控制台输出
  18. 强制将 stdout 的编码改为 UTF-8
  19. 场景 4:Python 源码文件本身的编码
  20. -- coding: utf-8 --
  21. 三、排查乱码的神器
  22. 输出:{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
  23. 四、总结与最佳实践
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Linux Vim 编辑器常用指令详解与模式切换指南
  • C++ 设计模式详解:分类、实现与核心应用
  • Stable Diffusion WebUI 本地部署完整教程
  • Ergo API 开发指南:如何构建 IRC 聊天机器人
  • Linux 工程化实战:构建你的第一个命令行工具项目
  • 华为 OD 机试双机位 C 卷:最小化最大单日做题时间算法题
  • 二分查找算法详解:基础查找与边界定位
  • Vue3 人机对话界面实现:流式请求与 ECharts 图表集成
  • Linux 性能实战:为什么使用写入时复制(COW)机制
  • Linux 新手基础工具指南:软件安装、Vim 操作与 GCC 编译
  • 基于随机森林的信用卡欺诈检测实战
  • Stack-Chan 机器人快速入门与配置指南
  • Linux 信号入门:进程通信机制与实战应用
  • GitHub 热门:支持国内股票分析的 AI 开源项目
  • ToDesk、顺网云与海马云运行 DeepSeek 模型性能对比评测
  • OpenClaw 多飞书机器人与多 Agent 团队协作实践
  • Linux 信号处理:可重入函数原理与实战规范
  • Linux 信号处理:可重入函数与安全实践
  • 2025 年 5 款主流 AI 办公工具实测:从 PPT 生成到远程协作
  • 一卡通核心交易平台国产数据库实践:架构、迁移与高可用落地

相关免费在线工具

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online