Python 3.15.0b4 已进入“最终计划 beta”窗口,但官方仍明确不建议用于生产。现在最有价值的动作不是把线上镜像直接切到 3.15,而是在独立 CI 轴上暴露依赖、编码、导入副作用、C 扩展和 free-threading 兼容问题,并把发现的问题反馈给上游。

当前到底处于什么发布阶段?

Python 3.15.0b4 官方发布页记录的发布日期是 2026 年 7 月 18 日,称其为最终计划 beta;页面同时强调它仍是预览版,不推荐生产使用。官方计划在 2026 年 8 月 4 日进入首个 release candidate,并希望 beta 4 后不再发生 ABI 变化,但这不是生产稳定性承诺。

PEP 790 发布日程给出的目标是 2026 年 10 月 1 日发布 3.15.0 final。迁移决策应该区分:

环境 当前建议
本地开发 可以建立独立 3.15 环境做兼容验证
CI 增加允许失败的 3.15 轴,逐步转为必过
预发布 用真实依赖锁和流量模型做回归
生产 继续使用已支持稳定版,等 final 与关键依赖成熟

这种分阶段门禁与双语内容原子发布的原则一致:测试通过、构建成功、部署完成与公网可用是不同状态。

第一步:建立不污染现有锁文件的测试轴

先从当前稳定分支创建 3.15 专用 CI,不要立刻修改全团队默认 Python:

strategy:
  matrix:
    python-version: ["3.12", "3.13", "3.14", "3.15"]
  fail-fast: false

steps:
  - uses: actions/setup-python@v6
    with:
      python-version: ${{ matrix.python-version }}
      allow-prereleases: true
  - run: python -m pip install -U pip
  - run: python -m pip install -r requirements.txt
  - run: python -X dev -W error::DeprecationWarning -m pytest

预发布轴一开始可以 continue-on-error,但必须生成可追踪的问题清单。不要把“允许失败”变成永久忽略;当核心依赖齐备后,把它提升为必过门禁。

第二步:先审依赖,再审业务代码

兼容失败常来自二进制 wheel 缺失,而不是 Python 源码。记录每个失败包属于哪一类:

  1. 没有 3.15 wheel,但可从源码构建。
  2. 构建工具不识别新版本或新 wheel tag。
  3. C/C++/Rust 扩展依赖已移除或变化的 C API。
  4. 依赖导入时修改全局状态,遇到 lazy imports 后行为改变。
  5. 包宣称兼容,但测试覆盖不包括 free-threaded 模式。

不要用 --only-binary=:all: 掩盖问题。可以分别运行“只接受 wheel”和“允许源码构建”两组检查,从而区分分发缺口和真实代码不兼容。

python -m pip install --only-binary=:all: -r requirements.txt
python -m pip check
python -c "import ssl, sqlite3, multiprocessing"

命令只是建议的验证模板;没有实际运行就不能声称项目兼容。

第三步:检查 UTF-8 默认编码的边界

Python 3.15 的重要变化之一是 UTF-8 成为默认编码。它减少了跨平台差异,但也可能让依赖本地编码的旧系统静默改变行为。优先搜索没有显式 encoding= 的文件操作:

rg "open\\(|Path\\(.*\\)\\.(read_text|write_text)" .

对配置、协议、导入导出文件显式写出契约:

from pathlib import Path

config = Path("config.json").read_text(encoding="utf-8")
Path("report.txt").write_text(report, encoding="utf-8", newline="\n")

测试至少覆盖中文路径、非 ASCII 内容、带 BOM 文件、无效字节与 Windows 换行。默认变成 UTF-8 不代表所有外部数据都是 UTF-8;网络协议和用户上传仍需显式验证。

第四步:把 lazy imports 当作语义变化测试

官方列出的主要特性包括显式 lazy imports。启动加速有吸引力,但导入副作用会变得更难推理。应搜索以下模式:

  • 模块导入时注册插件、路由或 signal。
  • import 触发环境检查、网络请求或日志配置。
  • 依赖导入顺序初始化全局单例。
  • 测试通过“先导入 A 再导入 B”才能成功。

正确方向是把副作用移动到显式的 create_app()register_plugins() 或生命周期钩子。FastAPI 应用尤其要避免把数据库连接、队列消费者和昂贵模型加载藏在 import 顶层。动态 SSR 双语站实践展示了清晰路由边界的重要性;运行时初始化也应同样可见。

第五步:普通应用需要立即迁移 abi3t 吗?

不需要。Python 官方 abi3t 迁移指南面向直接维护 C/C++ 扩展的作者。abi3t 是 Python 3.15 引入的 free-threaded Stable ABI 变体,可减少 future wheel 数量,但有 API 范围和可能的性能权衡。

按团队类型决策:

团队 建议
纯 Python 应用 验证依赖 wheel;不要自行改 ABI
使用 C 扩展的应用 跟踪上游 3.15 与 free-threaded 支持
手写 C/C++ 扩展 先证明线程安全,再评估 abi3/abi3t
Cython/PyO3 等生成器用户 等工具链明确支持,不抢跑

free-threaded “官方支持”也不等于你的依赖图线程安全。测试需覆盖共享可变状态、缓存、引用生命周期和锁顺序;单线程测试全部通过不能证明并发安全。

第六步:为 Web 应用建立两套性能基线

Python 版本升级可能同时改变解释器、JIT、导入和扩展行为。不要把端到端延迟变化归因于某一项特性。至少分别测:

  • 冷启动:进程启动到 readiness。
  • 热请求:p50/p95/p99 延迟和吞吐。
  • 内存:空闲 RSS 与稳定负载 RSS。
  • 后台任务:队列处理时间和取消延迟。
  • 错误:超时、连接池耗尽与 5xx。

使用相同依赖锁、相同容器限制和相同数据集对比 3.14 与 3.15。示例数字不能代替真实测量,也不要用解释器发布页的总体 benchmark 推断你的 FastAPI 服务收益。

第七步:设计可回滚的上线门禁

等到 final 之后,也不应“一次性全切”。推荐顺序:

  1. 构建 3.15 镜像并生成 SBOM。
  2. 锁定依赖哈希,确认 wheel 来源。
  3. 跑单元、集成、迁移、恢复与负载测试。
  4. 小比例 canary,比较错误率、延迟和内存。
  5. 保留上一稳定镜像与数据库兼容路径。
  6. 逐步扩容,任何异常按预设阈值回滚。

应用代码若写入新格式或改变序列化,解释器回滚不一定等于数据回滚。数据库 schema、队列消息与缓存版本必须保持双向兼容,或采用先扩展、后收缩的迁移。

常见误区

“Beta 4 后 ABI 不变,所以可以生产使用”

官方说的是目标,并且同一发布页明确不推荐生产。ABI 稳定目标不覆盖所有标准库 bug、依赖兼容和应用语义。

“安装成功就代表兼容”

安装只证明解析和构建完成。还需验证导入、启动、请求、后台任务、序列化、信号、子进程与关闭流程。

“free-threaded 会自动让 FastAPI 更快”

性能取决于瓶颈、依赖与线程安全设计。I/O 服务可能主要受数据库、网络和连接池影响;CPU 工作也需要实际 profile。

如何覆盖更容易漏掉的运行时边界?

解释器迁移测试不应只跑 HTTP happy path。按子系统建立矩阵:

子系统 必测行为
asyncio 取消、超时、TaskGroup 异常传播、关闭
multiprocessing 启动方式、pickle、worker 回收
TLS/HTTP 证书校验、代理、连接复用、超时
数据层 驱动导入、连接池、BSON/JSON、事务重试
CLI locale、stdin/stdout 编码、退出码
observability logging、trace context、profile 工具

-X dev 和 warning-as-error 模式之外,再跑一次正常生产参数,避免测试模式本身改变时序。对定时任务和 worker 进程,要验证 SIGTERM、租约释放和重复投递,而不是只看主 Web 进程。

库维护者还要增加哪些发布门禁?

库维护者需要把“源码兼容”和“分发兼容”分开:

  • python_requires 是否准确,不要在验证前宣称支持 3.15。
  • sdist 能否在干净环境构建。
  • 普通与 free-threaded wheel tag 是否匹配实际能力。
  • macOS、Windows、manylinux 的导入 smoke test 是否都运行。
  • 类型检查器、文档构建与示例是否使用同一公开 API。

如果生成预发布 wheel,使用清晰的 prerelease 版本与独立发布说明,避免普通用户误装。官方建议常规生产 release 等待 rc1,维护者可以提前上传测试产物,但要把它标记为测试入口。

FAQ

现在应该把最低版本提高到 3.15 吗?

通常不应该。beta 测试的目标是发现兼容问题,不是立刻放弃仍受支持的用户。最低版本取决于产品生命周期、依赖和安全支持策略。

可以在同一个 virtualenv 里切换解释器吗?

不要。虚拟环境路径、ABI 与已安装 wheel 绑定解释器。为 3.15 新建环境并重新解析或安装锁定依赖。

lazy imports 会自动启用并改变所有代码吗?

应以 3.15 当前官方文档和实际启动参数为准,不要仅凭特性名称推断。迁移测试仍值得清理 import 副作用,因为显式延迟导入或依赖使用该特性时会暴露问题。

可执行迁移清单

  • [ ] 3.15 独立 CI 轴存在,失败可追踪。
  • [ ] 依赖 wheel、源码构建与 pip check 分开验证。
  • [ ] 文件与协议编码显式化。
  • [ ] import 副作用迁移到生命周期函数。
  • [ ] C 扩展与 free-threaded 支持逐项记录。
  • [ ] 3.14/3.15 使用同一负载基线比较。
  • [ ] canary、阈值、回滚镜像和数据兼容方案齐备。
  • [ ] 只有 final 与关键依赖成熟后才进入生产评审。

最后,把迁移结果写成证据而不是口号:哪些测试运行过、哪些依赖仍阻塞、是否仅构建成功、是否进入 canary、是否真正全量。技术事实的表达也应遵循官方来源优先的 GEO/AEO 指南