python 2 到 python 3 字符串处理必须修改,因 str 与 bytes 彻底分离;文件操作需显式指定 encoding,二进制数据用 'rb' 模式;正则匹配前须确认类型;type hint 仅影响静态检查;第三方库兼容需实测多版本。

Python 2 到 Python 3 的字符串处理必须改
不改就炸,不是警告——str 和 bytes 在 Python 3 里是彻底分离的类型,而 Python 2 里 str 既当字节又当文本。你写的 open('file.txt').read().split('\n') 在 Python 2 能跑,在 Python 3 可能直接抛 UnicodeDecodeError。
常见错误现象:TypeError: a bytes-like object is required, not 'str'(比如传给 subprocess.Popen 的 stdin)、UnicodeEncodeError(print 非 ASCII 字符时)。
- 所有文件操作默认用文本模式打开,显式指定
encoding='utf-8',别依赖系统 locale - 二进制数据一律用
open(..., 'rb')+bytes操作,别用.decode()硬转 - 网络 I/O(如
socket.recv()、requests.Response.content)返回bytes,需要文本时明确.decode('utf-8', errors='replace') - 正则匹配前确认对象类型:用
re.compile(r'...').search(text)前,text必须是str;若源是bytes,得先 decode 或换用re.compile(b'...')
type hint 和 __future__ 导入不能解决运行时兼容
加 from __future__ import annotations 或写 def f(x: list[str]) -> None:,只影响类型检查器(如 mypy),对 Python 3.7 以下解释器根本没用——它们会直接报 SyntaxError。
使用场景:你想让同一份代码在 3.8+ 和 3.12 下都通过 mypy 检查,同时还能被旧版解释器加载(哪怕不执行 type check)。
立即学习“Python免费学习笔记(深入)”;
这是一款带缩略图的jquery焦点图特效代码。该焦点图通过鼠标滑过缩略图来进行前后导航,效果简朴,兼容IE8,非常实用。 使用方法 在页面中引入jquery和jquery.slides.js文件,以及样式文件style.css。
- 语法层面的兼容底线是 Python 3.6:它支持
from __future__ import annotations,也支持基本的list[int](PEP 585 之前得用typing.List[int]) -
typing.Union在 3.10+ 可写成int | str,但老版本不认,别混用 - 避免在运行时依赖
get_type_hints()—— 它在 3.9+ 才稳定支持字符串化注解,旧版容易崩
第三方库的兼容性比你想象中更脆弱
你以为 pip install requests 就万事大吉?错。很多库的“支持 Python 3.x”只是指最新小版本,比如 django 不支持 Python 3.11+,<code>numpy 在 3.10+ 里会因 C API 变动编译失败。
性能 / 兼容性影响:盲目升级 setuptools 或 pip 可能导致 pyproject.toml 构建失败,尤其在 CI 里用旧 base image 时。
- 查
setup.py或pyproject.toml里的python_requires,而不是只看 PyPI 页面写的 “3.6+” - 用
pip install --dry-run --python-version 3.9模拟安装,提前暴露冲突 - CI 中固定
pip版本(如pip>=22.0,),避免某天自动升级后构建挂掉 - 避免在
requirements.txt里写somepkg>=1.0—— 改成somepkg~=1.2.0或锁死小版本
sys.version_info 判断不能替代实际运行时行为检测
写 if sys.version_info >= (3, 8): use_walrus = True 是对的,但仅靠这个判断,挡不住 Literal 在 3.7 下不存在、graphlib.TopologicalSorter 在 3.8 下还没加、zoneinfo 在 3.9 之前得装 backport 这些事实。
容易踩的坑:有人用 hasattr(sys, 'version_info') 来“判断是否 Python”,结果在某些嵌入式解释器里失效;还有人把 sys.version_info[0] == 3 当万能开关,忘了 3.12 已经移除了 asyncio.async() 这种函数。
- 检测模块是否存在,用
try/except ImportError,别只靠版本号(比如zoneinfo可以 pip install backports.zoneinfo) - 检测函数是否存在,用
hasattr(asyncio, 'run')而不是sys.version_info >= (3, 7),因为有些发行版会 backport - 对关键路径(如 JSON 解析、时间处理),写单元测试覆盖多个 Python 小版本,光本地跑 3.11 没用
真正难的从来不是语法迁移,而是那些没报错但逻辑偏移的地方:比如 dict.keys() 在 3.7+ 是有序的,你写了依赖顺序的代码,却没在 3.6 CI 里测——等上线才发现 key 随机了。









