编程 Python 3.15 默认 UTF-8、frozendict 进 builtins:rc1 里会影响现有代码的改动

2026-09-30 21:06:27

Python 3.15 默认 UTF-8、frozendict 进 builtins:rc1 里会影响现有代码的改动

Python 3.15 是 3.14 之后的下一个稳定版本。rc1 于 2026-08-04 发布,rc2 计划在 2026-09-01;进入 rc 阶段后只接受经过审查的明确 bug 修复,此后 3.15 系列不再有 ABI 变化。对有 C 扩展的项目来说,这是一个可以开始跑 CI 的时间点。

来源:What's new in Python 3.15、Python Insider 发布公告。

PEP 686:默认编码改为 UTF-8,open() 不写 encoding 也走 UTF-8

Python 现在使用 UTF-8 作为默认编码,独立于系统环境变量。不带显式 encoding 的 I/O 操作会使用 UTF-8:

open('flying-circus.txt')                   # 3.15 起按 UTF-8 打开
open('flying-circus.txt', encoding='utf-8') # 显式写法,跨版本行为一致

这是本次对现有代码影响最直接的一条。在 locale 不是 UTF-8 的机器上(例如 LANG=C、LC_ALL=zh_CN.GBK 的 Linux,或默认代码页非 65001 的 Windows),3.14 及更早版本的 open('f.txt') 会按 locale 编码读写,而 3.15 一律按 UTF-8。结果是原本能跑通、读写 GBK/CP1252 内容的代码,升级后读到同样的字节会抛 UnicodeDecodeError,或者写出的字节序列和以前不一样。

排查这类问题不需要改逻辑,只要把每个隐式依赖 locale 的 open() 补上 encoding=,以及 str.encode()/bytes.decode()、subprocess 文本模式、pathlib.Path.read_text()/write_text() 这些同样吃默认编码的调用点。反过来,如果代码本来就假定 UTF-8,升级后反而不需要再显式传参。

PEP 810:显式惰性导入

显式惰性导入(lazy imports)用于加快启动时间。对启动时间敏感的命令行工具,这条比多数语法变化更值得测。

PEP 814 与 PEP 661:两个新内置类型

PEP 814 — frozendict。 它是 builtins 模块里的不可变类型,创建后不允许修改;不是 dict 的子类,直接继承自 object。当所有键和值都可哈希时,frozendict 可哈希;保留插入顺序,但比较时不考虑顺序。可以直接用作字典键、放进 set,或者当作模块级常量。

PEP 661 — sentinel。 新增 sentinel 内置类型,用于创建表示唯一的哨兵值,表示简洁。哨兵对象在复制时保持 identity,可在类型表达式中配合 | 运算符使用,且当可按模块和名称导入时可被 pickle。

PEP 798:推导式里支持解包

PEP 448 的解包语法扩展到了列表、集合、字典推导式,可以用 * 把任意数量的可迭代对象/字典合并进去:

[*part for part in parts]      # 列表推导里解包
{**d for d in dicts}           # 字典推导里合并

以前需要在推导式外面套一层 chain() 或多次 update() 的场景,写法可以简化。

PEP 799:profiling 包与 Tachyon 采样剖析器

新增专门的 profiling 包,把 Python 内置剖析工具组织到统一的命名空间下。其中 Tachyon 是高频统计采样剖析器,以 profiling.sampling 提供,可在不修改代码、不重启进程的情况下,对运行中的 Python 进程做低开销性能分析。容器里跑着的服务想临时看一眼热点,不用改启动参数就能采。

PEP 831:默认启用 frame pointers

默认启用 frame pointers,改善系统级可观测性。用 perf、eBPF 之类的系统工具抓 Python 进程栈时,帧链更完整。

JIT 与官方二进制

JIT 编译器有显著升级:相对标准解释器,x86-64 Linux 上有 8–9% 的几何平均性能提升;相对 tail-calling 解释器,AArch64 macOS 上有 12–13% 加速。

官方 Windows 64 位二进制现在使用 tail-calling 解释器;官方 macOS 二进制现在默认安装 free-threading 支持。也就是说 macOS 上的自由线程能力不用再单独处理安装方式,但依赖 GIL 假设的扩展需要自己确认兼容性。

其他这次一起进的改动

  • PEP 829:包启动配置文件。
  • PEP 728:带类型化额外项的 TypedDict。
  • PEP 747:用 TypeForm 标注类型形式。
  • PEP 800:类型系统中的不相交基类。
  • PEP 782:新的 PyBytesWriter C API,用于创建 Python bytes 对象。
  • PEP 803、PEP 820、PEP 793:free-threaded 构建的 Stable ABI(abi3t)及相关 C API。
  • PEP 788:C API 防止解释器终结时的使用。
  • 改进的错误信息,CLI 输出更多颜色。

已有的包如果带 C 扩展,rc 阶段是验证 abi3t 与 frame pointers/JIT 交互的窗口;纯 Python 项目优先级最高的仍是先把默认编码相关的调用点梳理一遍。

复制全文 生成海报 Python 语言特性 升级

推荐文章

程序员茄子在线接单