Python 2 与 Python 3 的 str/bytes 语义翻转是迁移失败主因:str 在 Python 2 中为字节,在 Python 3 中为 Unicode,不可隐式转换;读文件、网络响应、数据库交互及 print 语法均需显式处理编码与类型。

str 和 bytes 类型语义翻转是迁移失败最直接的根源——Python 2 的 str 是字节容器,Python 3 的 str 是 Unicode 文本,二者不能隐式转换。不改代码就切解释器,几乎必出 UnicodeDecodeError、TypeError: expected str, got bytes 或静默乱码。
读文件不指定 encoding 就崩
Python 2 的 open('data.txt').read() 默认按系统编码(如 Windows 上是 gbk)解码,常“侥幸”成功;Python 3 默认用 utf-8,遇到非 UTF-8 文件直接抛 UnicodeDecodeError。
- 必须显式声明:用
open('data.txt', encoding='utf-8')或open('data.txt', encoding='gbk') - 若不确定编码,先用
chardet.detect()探测,再传给encoding - 二进制场景(如图片、PDF)仍用
open(..., 'rb'),返回bytes,别调.decode()
网络响应体 content 是 bytes,不是 str
requests.get(url).content 在 Python 3 中永远是 bytes,而开发者常习惯性写 .content.split(b'\n') 或直接 .content.replace('a', 'b')——后者在 Python 3 下报 TypeError,因为 bytes 只接受 bytes 参数。
- 文本处理前必须解码:
resp.content.decode('utf-8').split('\n') - 若响应头没指定 charset,别硬写
utf-8,先看resp.encoding或用chardet.detect(resp.content) - 更稳妥的做法是优先用
resp.text(requests 自动解码),但要注意它可能 fallback 到错误编码
数据库字段传参类型错配
Python 2 下把 str(字节)传给 PostgreSQL 的 TEXT 字段能过;Python 3 中若传 bytes 给期望 str 的参数(如 cursor.execute("INSERT...", (b'hello',))),psycopg2 直接 raise TypeError。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 检查所有 SQL 参数:确保字符串类参数是
str,不是bytes - 从文件/网络读来的数据,先 decode 再进 DB;DB 返回的字符串默认是
str,别再 encode - MySQL 驱动(如
mysql-connector-python)同样敏感,尤其对charset连接参数和字段值类型
print 调试残留引发 SyntaxError 或逻辑断裂
print 'debug:', x 在 Python 3 下是语法错误;更隐蔽的是,有些日志装饰器或 AST 分析工具(如旧版 coverage.py)会因 print 从语句变函数而解析失败。
立即学习“Python免费学习笔记(深入)”;
- 全局搜索并替换所有裸
print语句为print()函数调用 - 别依赖
from __future__ import print_function“打补丁”,它只作用于当前文件,不传导到被 import 的模块 - 调试统一改用
logging.debug('%r', x),避免类型和编码双重风险
bytes → 误当 str 传给 requests → requests 发出去再被后端当 UTF-8 解码 → 服务端收到乱码。这种链路式编码污染,查起来要逐层确认每个接口的输入/输出类型,不能只盯最后一行报错。

















