Skip to content

资料库 · Python 工程实践

第 ① 卷,条目 1–20。来源以 blog.python.org(Python Insider 官方博客)、snarky.ca(Brett Cannon,CPython 核心开发者、打包标准的主要推动者)、pythonspeed.com(Itamar Turner-Trauring)为主。

这一卷的重点是版本演进和语言机制,打包与 Docker 的实操内容集中在 第四卷


版本演进与发布节奏

1. Python 3.15.0 candidate 1 is here!

来源:Python Insider 官方博客,2026 年 8 月。

读它解决什么:想知道 3.15 到底什么时候能用在生产上,以及 rc 阶段还允许改什么。

要点

  • 3.15 已进入 release candidate 1,按 CPython 的惯例,rc 之后只接受 release blocker 级别的修复,特性集已冻结
  • 这是 3.15 正式版之前最后的公开测试窗口

我的补充:rc 是该开始测但还不该上线的节点。我的做法是 rc 一出就在 CI 里加一条 3.15 的矩阵,允许失败(continue-on-error),这样正式版发布那天你已经知道自己的依赖树哪里会炸,而不是那天才开始查。别在 rc 阶段就把生产切过去——rcfinal 之间偶尔会有 ABI 层面的收尾调整,编译型扩展需要重新构建。

阅读原文 →

2. Python 3.14.7 and 3.13.15 are now available!

来源:Python Insider 官方博客,2026 年 8 月。

读它解决什么:确认当前 3.14 与 3.13 的最新补丁号,以及要不要跟这次升级。

要点

  • 3.14.7 与 3.13.15 同期发布,属于常规维护版本
  • 两条分支仍在同步接收 bugfix

我的补充:patch 版本升级几乎总该跟,尤其是 Docker 基础镜像。但要注意别在 Dockerfile 里写 FROM python:3.14——它是浮动 tag,你今天构建拿到 3.14.7,下个月同一份 Dockerfile 拿到 3.14.9,构建就不可复现了。写全 FROM python:3.14.7-slim 才是对的,升级作为一次显式提交。这个原则和第四卷里"可复现构建"那几条是一回事。

阅读原文 →

3. Python 3.12.14, 3.11.16 and 3.10.21 are now available!

来源:Python Insider 官方博客,2026 年 8 月。

读它解决什么:还在跑 3.10–3.12 的老项目,判断这次维护版本要不要升。

要点

  • 三条老分支同期出补丁版本
  • 3.10 已进入 security-only 阶段,这类同步发布通常意味着修的是安全问题

我的补充:三条分支同一天一起发版,这个信号本身值得注意——常规 bugfix 各分支节奏是错开的,只有安全修复才会强制对齐。看到这种同步发布,优先级应该当安全更新处理,别排到下个迭代。查具体修了什么去 changelog,公告本身一般不写 CVE 细节。

阅读原文 →

4. Python 3.15.0 beta 4 is here!

来源:Python Insider 官方博客,2026 年 7 月。

读它解决什么:了解 3.15 beta 阶段的收尾情况。

要点

  • beta 4,3.15 特性冻结之后的第四个 beta
  • beta 阶段是第三方库适配 3.15 的主要窗口

我的补充:beta 阶段最该做的事是给自己依赖的库提 issue。到 rc 才发现某个 C 扩展没适配,那时候维护者也来不及了。如果你的项目依赖 numpy/pydantic/lxml 这类带编译扩展的包,beta 期间去它们的 issue 列表搜一下 3.15,通常已经有跟踪 issue,能直接看到进度。

阅读原文 →

5. Python 3.15.0 beta 1 is here!

来源:Python Insider 官方博客,2026 年 5 月。

读它解决什么:确认 3.15 的特性冻结时间点。

要点

  • beta 1 是 3.15 的特性冻结节点,之后不再接受新特性
  • 从这一版开始,3.15 的 API 面可以当作稳定的来看

我的补充:beta 1 的日期是一个有用的坐标——任何在 beta 1 之后才出现的"3.15 新特性"介绍文章,大概率是把 alpha 阶段被撤掉的提案当成了既定事实。我读版本特性文章有个习惯:先看文章日期落在 beta 1 之前还是之后,之前的一律去 What's New 官方文档复核。

阅读原文 →

6. Python 3.14.0 (final) is here!

来源:Python Insider 官方博客,2025 年 10 月。

读它解决什么:3.14 正式发布的公告,是判断"该不该把主力版本切到 3.14"的起点。

要点

  • 3.14.0 正式版发布,按 CPython 的年度节奏,10 月发版符合惯例
  • 从这一版起 3.14 进入 bugfix 阶段

我的补充:正式版发布当天不是迁移的最佳时机。我的经验是等到 .2.3(差不多发布后两三个月),生态里主要的编译型包都出了 wheel,这时候迁移最省事。太早迁移,你会花大量时间在"某个包没有 3.14 的 wheel,pip 尝试本地编译,缺 header 失败"这类和你业务无关的问题上。

阅读原文 →

7. CPython: 36 Years of Source Code

来源:Python Insider 官方博客,2026 年 3 月。

读它解决什么:想从代码量与结构变化的角度,看 CPython 这三十多年长成了什么样。

要点

  • 以 CPython 代码库的历史增长为题,跨度 36 年
  • 属于回顾类内容,不是特性公告

我的补充:这类回顾读起来轻松,但有个实用价值:它能让你对"标准库为什么这么难改"有直观感受。很多人抱怨某个标准库模块设计过时(urllibdatetime 的时区处理),看过代码库的年龄结构就明白,向后兼容的包袱是按几十年计的。这也是为什么新东西倾向于走 v2 命名(math/rand/v2 在 Go 那边是同一个思路,见 第二卷)而不是原地改。

阅读原文 →

8. Python 3.15's JIT is now back on track

来源:Python Insider 官方博客,2026 年 3 月。

读它解决什么:关心 CPython 的 JIT 进展,判断 3.15 的 JIT 值不值得期待。

要点

  • 标题明确说 3.15 的 JIT 工作"回到正轨",说明此前遇到过阻塞
  • JIT 从 3.13 开始以实验特性存在,一直未默认开启

我的补充:CPython 的 JIT 到目前为止都是默认关闭的实验特性,需要构建时显式开启。所以看到"JIT 有进展"不要理解成"下个版本我的代码就快了"。真正影响你的性能的,绝大多数时候还是算法和 I/O,不是解释器。真要在当下拿到 JIT 收益,PyPy 或把热点挪到 Rust/C 扩展(见第三卷)比等 CPython 的 JIT 现实得多。

阅读原文 →

9. Rust for CPython Progress Update April 2026

来源:Python Insider 官方博客,2026 年 4 月。

读它解决什么:想知道 CPython 自身引入 Rust 的进展与边界。

要点

  • CPython 内部使用 Rust 的进度更新,2026 年 4 月
  • 属于持续系列的一期,说明这件事在推进而非一次性讨论

我的补充:这件事对普通用户的影响主要在构建端:一旦 CPython 本体的某些部分需要 Rust 工具链,从源码编译 Python 的门槛就变了(交叉编译、非主流架构、老发行版上尤其明显)。如果你有"在 CI 里从源码构建特定 Python 版本"的流程,值得跟一下这个系列。用官方二进制或 uv python 管理版本的人基本无感。

阅读原文 →

10. Mitigated API authentication bypass for python.org download metadata

来源:Python Insider 官方博客,2026 年 6 月。

读它解决什么:了解一次真实发生在 Python 官方基础设施上的认证绕过事件。

要点

  • python.org 下载元数据的 API 出现认证绕过,已被缓解
  • 影响面是元数据,公告标题限定了范围

我的补充:供应链这块最容易被忽略的一环就是元数据。你校验了安装包的哈希,但哈希本身是从哪来的?如果元数据可以被改,"校验通过"就没有意义。这也是为什么 PEP 740 的数字证明(attestation)和 pylock.toml 里带 attestation 那条设计(见本卷第 15 条)是必要的——信任链要能追到发布者的身份,而不是止步于某个可写的 API。

阅读原文 →


语言机制与类型系统

11. Unravelling t-strings

来源:Brett Cannon(snarky.ca),CPython 核心开发者。

读它解决什么:想搞清 t-string(模板字符串)到底是什么、和 f-string 差在哪。

要点

  • 主题是 t-strings 的机制拆解,作者是 CPython 核心开发者
  • "unravelling" 说明是从底层行为往上讲,不是用法教程

我的补充:t-string 解决的是 f-string 最危险的那个问题:f-string 立刻求值成字符串,所以你没有任何机会在拼接之前做转义。f"SELECT * FROM t WHERE id={uid}" 就是 SQL 注入的标准写法。t-string 把字面量和插值部分分开交给你,让库作者能实现"安全拼接"的语义。这个博客的 Pages Functions 里凡是拼接外部输入的地方,我都刻意避开了 f-string 风格的直接拼接——同一个道理,不同语言。

阅读原文 →

12. The varying strictness of TypedDict

来源:Brett Cannon(snarky.ca)。

读它解决什么TypedDict 用起来行为不一致,想知道严格性到底由什么决定。

要点

  • 主题是 TypedDict 在不同情况下严格程度的差异
  • 标题的 "varying" 直指同一个特性存在多种严格度这件事

我的补充TypedDict 最容易踩的是它不做运行时校验。类型检查器(mypy/pyright)满意,不代表运行时那个 dict 真的长这样——从 JSON 反序列化来的数据完全可能缺键,代码照跑,直到 KeyError。我的习惯是:TypedDict 只用来标注内部已经构造好的结构;凡是从外部(HTTP body、配置文件)进来的,一律过一层 pydantic 或手写校验。类型标注不是校验,这条在 TypeScript 那边也一样(见 前端第三卷)。

阅读原文 →

13. CLI subcommands with lazy imports

来源:Brett Cannon(snarky.ca)。

读它解决什么:CLI 工具启动慢,想知道怎么用惰性导入把子命令的开销推迟。

要点

  • 主题是给 CLI 的子命令做惰性导入
  • 隐含前提:顶层一次性导入所有子命令的依赖会拖慢启动

我的补充:这条对写命令行工具的人是立刻能用的。Python CLI 启动慢,八成不是你的代码慢,是 import 慢——顶部 import requests, pandas, boto3 三行就能吃掉几百毫秒,而用户只是敲了 mytool --help。诊断用 python -X importtime -m mytool 一跑就能看到耗时排行。改法就是把重依赖挪到函数体内部,只在真正执行那个子命令时才导入。代价是 import 错误从启动时推迟到运行时暴露,所以 CI 里得有能覆盖每个子命令的 smoke test。

阅读原文 →

14. Why I wrote PEP 832 — virtual environment discovery

来源:Brett Cannon(snarky.ca)。

读它解决什么:想理解"虚拟环境该怎么被发现"这个问题为什么需要一份 PEP。

要点

  • 作者自述写 PEP 832 的动机,主题是虚拟环境的发现机制
  • 是动机与背景说明,不是规范正文

我的补充:这个问题的现实痛点是:.venvvenvenv、Poetry 藏在 ~/.cache 里、Conda 有自己一套、uv 又是一套——每个工具都得重新猜一遍"当前项目的环境在哪",猜错了就装到系统 Python 里去。有了统一的发现约定,编辑器、linter、任务运行器才能对齐。读动机类文章的价值在于:你能知道一个规范排除了哪些方案,这比只读最终规范有用得多。

阅读原文 →

15. Why pylock.toml includes digital attestations

来源:Brett Cannon(snarky.ca)。

读它解决什么:想知道锁文件里为什么要放数字证明,而不只是哈希。

要点

  • 解释 pylock.toml(Python 标准锁文件格式)为何纳入数字证明
  • 作者是该规范的主要推动者之一

我的补充:哈希回答的是"文件有没有被改过",attestation 回答的是"这个文件是不是那个人发的"。两者不能互相替代。只有哈希的情况下,攻击者拿到 PyPI 发布权限后可以发一个新版本、连带新哈希,你的锁文件一升级就把恶意包锁进去了,全程哈希校验都通过。attestation 把发布行为绑到可验证的身份(比如 GitHub Actions 的 OIDC 身份)上,才能识别出"这次发布不是从项目的 CI 出来的"。和第 10 条那次元数据事件是同一个信任链问题的两端。

阅读原文 →

16. Why it took 4 years to get a lock files specification

来源:Brett Cannon(snarky.ca)。

读它解决什么:想知道 Python 的锁文件标准为什么耗了四年,以及难点在哪。

要点

  • 复盘 Python 锁文件规范历时四年的过程
  • 由参与者本人写,属于一手的过程记录

我的补充:难点不在文件格式,在于Python 的依赖解析本身就是环境相关的。同一份依赖声明,在 Linux/macOS、CPython/PyPy、有无 GPU 的机器上解出来的结果不一样,因为 sys_platformpython_version 这些 marker 会改变依赖树。要么锁文件只对单一平台有效(好锁但不通用),要么它得编码全部平台组合(通用但巨大)。理解了这个张力,你就明白为什么 pip freeze 的输出从来不是真正的锁文件,它只是当前这台机器的快照。

阅读原文 →

17. State of WASI support for CPython: March 2026

来源:Brett Cannon(snarky.ca),2026 年 3 月。

读它解决什么:想知道 CPython 跑在 WASI(WebAssembly 系统接口)上的现状。

要点

  • CPython 的 WASI 支持进度报告,时间点 2026 年 3 月
  • 系列性的状态更新,说明这是长期推进的工作

我的补充:WASI 版 CPython 的意义在于能在没有进程隔离的地方跑 Python——比如 Cloudflare Workers 这类边缘运行时。这个博客的 Pages Functions 现在只能写 JS/TS,因为 Workers 运行时没有 Node 的 fs/path,更没有 Python 解释器。如果 WASI 这条线成熟,边缘函数写 Python 就有戏。但要有预期:文件系统和网络在 WASI 下都是受限的,大部分依赖 C 扩展的库短期内跑不起来。

阅读原文 →


性能与底层

18. Faster floating point math with Rust's new API

来源:Itamar Turner-Trauring(pythonspeed.com)。

读它解决什么:在 Rust 里做浮点计算,想知道新 API 能怎么提速。

要点

  • 主题是利用 Rust 的新浮点 API 提升数学运算速度
  • 作者长期写 Python 性能,此文从 Rust 侧切入

我的补充:这条放在 Python 卷里不是错放——Python 的数值性能路线现在基本就是"热点下沉到 Rust 扩展"(polarspydantic-coreruff 都是这条路)。浮点这块要知道的关键点是:编译器默认不敢重排浮点运算,因为浮点加法不满足结合律,重排会改变结果。所以 a+b+c 不能自由变成 a+(b+c),自动向量化就被卡住了。允许"快速但不严格"的浮点语义,是解锁 SIMD 的前提,代价是你得接受结果的最后几位可能有差异。做金额计算的场合别开这类优化。

阅读原文 →

19. 8× faster binary search: from compiled code to mechanical sympathy

来源:Itamar Turner-Trauring(pythonspeed.com)。

读它解决什么:想看一个"算法复杂度没变但快了 8 倍"的具体案例。

要点

  • 二分查找提速 8 倍,路径是从编译产物一直看到硬件行为
  • "mechanical sympathy" 指按硬件的实际工作方式来写代码

我的补充:这条是理解"O(log n) 不等于快"的最好例子。教科书里的二分查找每一步都是 if 分支,而分支预测器对二分查找的跳转方向基本猜不中(每次比较结果都近似随机),于是每一层都可能是一次流水线冲刷。无分支(branchless)写法用算术代替跳转,虽然指令更多,但没有误预测惩罚,反而更快。另一半收益来自缓存局部性——二分查找的访问模式在大数组上几乎每次都是 cache miss。这类优化的适用范围很窄,但它能纠正一个很普遍的误解:复杂度分析只算比较次数,不算每次比较的成本。

阅读原文 →

20. Timesliced reservoir sampling: a new(?) algorithm for profilers

来源:Itamar Turner-Trauring(pythonspeed.com)。

读它解决什么:关心采样式 profiler 的内部原理,或者想知道怎么在固定内存下做有代表性的采样。

要点

  • 提出一种用于 profiler 的分时段蓄水池采样算法
  • 标题里的 "new(?)" 是作者自己对原创性的保留

我的补充:profiler 的核心矛盾是:要长时间跑,又不能无限存样本。经典蓄水池采样能在固定内存下均匀采样,但对 profiler 不够——你通常关心"最近这段时间在干什么",而均匀采样会让开头和结尾的权重一样。按时间分片再各自蓄水池,就能既控制内存又保留时间分布。这个思路可以直接搬到日志采样上:高 QPS 服务全量记日志不现实,按分钟分片各留 N 条,比全局随机丢弃更有用,因为你不会丢掉某个安静时段的全部证据。

阅读原文 →


本卷小结

三个带走的结论:

  1. 版本号是可信度的锚点。 alpha / beta / rc / final 各有各的语义,读任何"新特性"文章都先确认它写在哪个阶段。这一卷里 3.15 的 alpha 到 rc 跨了将近一年,中间被撤回的提案不算少。
  2. 类型标注不是运行时校验。 TypedDict 让检查器满意,不保证那个 dict 真的长这样。外部数据必须过真正的校验层。
  3. 哈希和身份是两件事。 哈希证明文件没被改,attestation 证明是谁发的。供应链安全需要两者,第 10 条那次元数据事件就是只有前者不够的现实例证。

上一卷: ← 总览 · 下一卷: ② Go 语言与并发 →