首页/开发/正则与编码速查/Python 编解码接口的正确用法

Python 编解码接口的正确用法

Python 3 把字符串与字节严格分成 str 和 bytes,转换必须显式调用 encode/decode;默认编码随环境变化,因此文件与标准输入输出都要显式指定 encoding,否则换机器就会出现乱码或报错。

正则与编码速查开发更新于 2026-10-17
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

str 与 bytes 的边界

Python 3 里 str 是 Unicode 码点序列,bytes 是原始字节序列,二者之间的转换必须显式发生:str.encode(编码) 得到 bytes,bytes.decode(编码) 得到 str。这个设计把编码问题的发生点暴露在代码里,代价是任何涉及输入输出的操作都需要明确编码。默认值来自运行环境的 locale:Windows 上常是 cp936,Linux 上常是 UTF-8,同一份代码在不同机器上的行为会不同。

基本信息

方向str→bytes 用 encode;bytes→str 用 decode
默认编码来自 locale.getpreferredencoding(False),随平台变化
文件读写open(path, encoding='utf-8') 显式指定最稳妥
标准输出受 sys.stdout.encoding 影响,Windows 控制台常为 cp936
UTF-8 模式PYTHONUTF8=1 或 python -X utf8 可让默认编码固定为 UTF-8
万能字节通道latin-1 能把任意字节一对一映射为字符,便于无损往返

典型使用场景

  • 读取外部文件:来自 Windows 或老系统的文件多为 GBK,需要显式指定编码
  • 网络与接口:请求体与响应体是字节,解码前必须先确认对方使用的编码
  • 日志与控制台输出:中文在 Windows 控制台报编码错误,需要改输出编码或环境变量
  • 字节保真处理:把二进制内容放进文本容器时用 latin-1 做无损搬运
  • 跨平台脚本:固定 UTF-8 模式,避免开发机与服务器行为不一致

正确与错误对照

正确与错误对照
# 正确:两个方向显式指定编码
python -c "print('中文'.encode('utf-8'))"              # b'\xe4\xb8\xad\xe6\x96\x87'
python -c "print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))"   # 中文
# 显式指定文件编码,不依赖系统默认值
python -c "print(open('a.txt', encoding='utf-8').readline())"
# 读到 GBK 文件时显式声明
python -c "print(open('gbk.txt', encoding='gbk').readline())"
# 经典错误:把 bytes 直接当 str 用,结果得到 b'...' 字面量
python -c "print(str(b'abc'))"                          # 输出 b'abc',不是 abc
# 控制台输出编码固定(避免 Windows 下 UnicodeEncodeError)
python -X utf8 -c "print('中文')"

操作与语义对照

操作输入/输出注意点
str.encode('utf-8')str → bytes目标编码表示不了的字符会按 errors 策略处理
bytes.decode('utf-8')bytes → str字节非法时按 errors 策略处理,默认抛异常
open(..., encoding=)文本模式读写不指定则用平台默认编码
open(..., 'rb') / 'wb'二进制模式得到或写入 bytes,不涉及编码
len(s) / len(b)码点数 / 字节数两者口径不同,长度校验要明确用哪个
latin-1 往返bytes ↔ str 无损用于字节保真,不作为展示编码
str(bytes_obj) 不会解码,它返回的是 b'...' 形式的字面量字符串,这是排查时最常见的假象;要得到文本必须用 decode。同理,b'str' 也不会自动编码。
依赖默认编码的程序在换平台后行为不同:同一份脚本在 Windows 上按 cp936 读写,在容器里按 UTF-8 读写,产出的文件可能无法互相解析。凡涉及外部输入的读写,都应显式写出编码名称。
Python 3 的 len(str) 按码点计数,与 UTF-8 字节数、显示宽度都不同;需要按字形簇计数时要引入图形分割相关库,不要用 len 直接判断用户可见字符数。

易错点

  • 混淆 encode 与 decode 方向:拿到 bytes 却调用 encode,报属性错误或语义完全错 → 记住「从字节到文本用 decode」
  • 依赖系统默认编码读写文件:本地正常、服务器乱码 → 所有 open 调用显式指定 encoding
  • 用 str(bytes) 期望得到文本:得到 b'...' 字面量并写进数据 → 使用 decode 或 f-string 格式化
  • 在文本模式读取二进制文件:遇到非法字节抛异常或产生替换字符 → 用 'rb' 读取后按真实编码解码
  • 控制台打印非 ASCII 字符报编码错误:受 sys.stdout.encoding 限制 → 设置 PYTHONIOENCODING 或用 UTF-8 模式运行

数据来源与参考

  • Python 官方文档:Unicode 与文本编解码(str.encode / bytes.decode)
  • Python 官方文档:io 模块与 open 的 encoding 参数
  • PEP 540 / PEP 597:UTF-8 模式与默认编码相关提案

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/regex/python-encode-decode.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​​​​​‌‌‌‌​​‌​‌‌‌​‌​​​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​