Python 3.15 free-threaded 扩展兼容要先检查什么
我在整理 Python 3.15 升级清单时,最先排除的误区是“解释器升级成功,就等于 free-threaded 已经可用”。Python 3.15.0 已于 2026 年 10 月 9 日发布,free-threaded 构建也更值得被放进真实项目的兼容矩阵,但带 C/C++ 扩展的项目仍然要单独检查扩展声明、wheel 标签和导入后的 GIL 状态。
官方发布页:https://www.python.org/downloads/release/python-3150/
free-threaded 官方说明:https://docs.python.org/3.15/howto/free-threading-python.html
先确认运行的是哪一种 CPython 构建,再确认每个扩展是否明确支持 free-threading,最后才判断 wheel 与 abi3t 是否能降低构建维护成本。只升级 Python 版本,不能替代这三步。
Python 3.15 的变化,先看清“版本”和“构建”
Python 3.15 的发布信息把 free-threaded 相关的 C API 和稳定 ABI 改进列入了重要变化,但这不表示所有项目默认切换到了禁用 GIL 的运行方式。CPython 从 3.13 开始提供 free-threaded 构建;普通构建和 free-threaded 构建是兼容矩阵中的两个不同维度。
对应用维护者来说,第一张表应至少记录三项:Python 主版本、解释器是否支持 free-threading、进程启动后 GIL 是否实际关闭。官方文档建议使用 sysconfig.get_config_var("Py_GIL_DISABLED") 判断构建能力,使用 sys._is_gil_enabled() 观察当前进程状态。
import sys
import sysconfig
# 先判断解释器是否具备 free-threaded 构建能力。
build_supports_free_threading = sysconfig.get_config_var("Py_GIL_DISABLED") == 1
# 再观察当前进程的 GIL 状态;不同构建或导入扩展后结果可能不同。
gil_is_enabled = sys._is_gil_enabled()
print({
"build_supports_free_threading": build_supports_free_threading,
"gil_is_enabled": gil_is_enabled,
})
这段代码只用于读取运行时状态,不是性能测试。若构建支持 free-threading,但 gil_is_enabled 仍为真,就不要把这次启动当成“已经验证了无 GIL 并发”。

第二个检查点:扩展导入会不会把 GIL 重新打开
free-threaded 兼容的关键不只是 Python 代码能否启动,而是 C API 扩展有没有明确告诉 CPython“我支持 GIL 被禁用”。官方扩展指南区分了多阶段初始化和单阶段初始化:前者可以在模块槽中声明 Py_mod_gil,后者需要在 free-threaded 构建下调用 PyUnstable_Module_SetGIL。
如果扩展没有做相应声明,free-threaded CPython 在导入它时可能打印警告并重新启用 GIL。于是应用表面上没有崩溃,线程也可以继续运行,但你原本期待的并行执行路径已经改变。发布前要把“成功导入”和“仍保持 GIL 禁用”分开记录。
#if PY_VERSION_HEX >= 0x030D0000
// 多阶段初始化的扩展,用模块槽声明不依赖 GIL。
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
#endif
#ifdef Py_GIL_DISABLED
// 单阶段初始化扩展只在 free-threaded 构建中调用该声明。
PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED);
#endif
上面的片段是扩展迁移时要核对的结构示意,不能直接代替项目现有的错误处理和模块初始化代码。尤其要注意:声明“不依赖 GIL”只是运行时契约的一部分,扩展自己的全局缓存、静态状态和线程入口仍然需要同步设计。
第三个检查点:wheel 标签是否真的匹配
free-threaded 构建的二进制分发会通过 t 后缀表达差异,例如 CPython 3.15 的版本特定构建可对应 cpython-315t。因此,普通 cpython-315 wheel 能否用于 free-threaded 环境,不能凭文件名相似来判断,应交给构建工具和项目支持矩阵确认。
如果扩展迁移到 Python 3.15 引入的 abi3t,稳定 ABI 可以覆盖 free-threaded 构建,并且官方文档说明它也能被非 free-threaded 构建使用。对应的 wheel ABI 标签会出现 abi3.abi3t。这能减少按每个 CPython 小版本分别构建的数量,但不会替你解决线程安全问题。
| 检查对象 | 关注什么 | 不要得出的结论 |
|---|---|---|
cpython-315 | 普通 CPython 3.15 的版本特定构建 | 不能据此证明支持 free-threaded |
cpython-315t | 面向 3.15 free-threaded 构建的版本特定 wheel | 不能据此证明多版本稳定 ABI 兼容 |
abi3t | 面向 free-threaded 构建的稳定 ABI 变体 | 不能据此证明扩展内部状态已线程安全 |
| 源码构建 | 编译宏、构建工具、平台和测试矩阵 | 不能只看构建成功就跳过并发测试 |

什么时候值得迁移到 abi3t
我会把 abi3t 当成“减少构建分支”的工程选择,而不是 free-threaded 的快捷开关。适合评估它的情况通常是:扩展已经能够遵守受限 API,项目愿意把 Python 3.15 作为最低目标之一,并且构建工具已经能正确产生对应标签。
如果扩展依赖稳定 ABI 之外的 API,或者仍要支持较老的 Python 版本,就要比较两条路线:继续为各版本和两种构建分别产出 wheel,或者用预处理条件保留旧版本路径、为新构建增加 abi3t 适配。官方迁移指南也提醒,稳定 ABI 的限制可能带来改造成本,不能只看最终 wheel 数量。
更重要的是,abi3t 只表达 ABI 兼容范围。它不替你验证以下问题:全局缓存是否有锁、原生线程回调是否附着了有效的线程状态、阻塞 I/O 是否正确释放线程状态、以及多线程同时访问对象时是否仍符合扩展自己的约束。
把兼容矩阵安排成一次可重复的检查
一个实用的最小矩阵可以分为普通构建和 free-threaded 构建两列,再把纯 Python 路径和带扩展路径分开。每一格不必一开始就追求完整压测,但至少要能记录安装、导入、核心调用和并发场景的结果。
- 记录解释器:版本、平台、构建类型,以及
Py_GIL_DISABLED和sys._is_gil_enabled()的状态。 - 记录扩展:是否使用 C/C++、采用单阶段还是多阶段初始化、是否声明支持 free-threading。
- 记录分发:安装到的 wheel 文件名、Python/ABI/平台标签,以及是否从源码构建。
- 记录行为:导入时是否出现 GIL 重新启用警告,核心 API 是否能在多个线程中安全工作。
- 记录交付:普通构建与 free-threaded 构建是否都保留回退 wheel,发布说明是否写清支持范围。
对于只使用纯 Python 的项目,检查重点会轻一些;对于 NumPy、数据库驱动、图像处理、科学计算或自研扩展较多的项目,真正的风险通常集中在二进制依赖链,而不在业务代码表面。
升级前最容易漏掉的三件事
第一,不要把 macOS 或 Windows 安装器里出现 free-threaded 选项,理解成所有第三方 wheel 都自动支持。第二,不要把导入成功理解成 GIL 没有重新启用。第三,不要把 abi3t 标签理解成线程安全认证。
我的建议是先把这次升级当成“增加一个运行时维度”,为普通构建保留稳定路径,再逐个扩展评估 free-threaded 支持。如果某个扩展暂时不兼容,明确记录它会让 GIL 重新启用或暂时不进入该构建,比盲目宣称全链路支持更容易维护。
常见问题
Python 3.15 默认就是 free-threaded 吗?
不是。Python 3.15 包含对 free-threaded 生态更完整的支持,但普通构建与 free-threaded 构建仍需区分,最终状态要以解释器构建信息和运行时检查为准。
扩展没有声明支持 free-threading 会立刻报错吗?
不一定。官方文档说明这类扩展可能触发警告并重新启用 GIL,所以“程序能跑”与“程序仍在无 GIL 模式运行”是两个不同结论。
用了 abi3t 就不用为不同平台测试了吗?
不是。abi3t 主要减少 ABI 维度的构建分支,平台、编译器、原生线程、数据竞争和业务并发行为仍需要按项目支持范围测试。
Python 3.15 lazy imports 对 CLI 启动优化有什么启发
- 上一篇
- Python 3.15 lazy imports 对 CLI 启动优化有什么启发
- 下一篇
- 90fps画质安装前怎么核对权限?存储访问、免Root与兼容边界说明
-
- 科技周边 · 业界新闻 | 1小时前 | 虚拟线程 · 虚拟线程 OpenJDK JFR VirtualThreadPinned Java Flight Recorder
- OpenJDK 虚拟线程与 JFR 观测如何协同
- 480浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 |
- 浏览器 View Transition 跨文档能力为何值得关注
- 338浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 | 命令行 · 性能优化 · python · Python教程 · 语言特性 · Python 3.15 PEP 810 lazy imports CLI启动 启动性能
- Python 3.15 lazy imports 对 CLI 启动优化有什么启发
- 404浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 |
- Redis 哈希字段过期能力怎样改变缓存键设计
- 187浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 | Redis · 消费组 Redis Streams Redis 8.2 XACKDEL XDELEX
- Redis 8.2 Stream 命令细粒度确认适合哪些消费组场景
- 153浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 |
- MCP 规范新增缓存元数据后客户端如何处理 TTL
- 406浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 | 开发工具 · 业界新闻 · Go工具链 Go 1.27 go doc 可执行示例 go doc -ex
- Go 1.27 的 go doc -ex 如何改变示例检索体验
- 119浏览 收藏
-
- 科技周边 · 业界新闻 | 2天前 | 人工智能 · 业界新闻 · 开发实践 Stack Overflow Survey AI信任 代码助手
- Stack Overflow 2026 调查中的 AI 信任与开发实践
- 120浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 452次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 520次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 536次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 482次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 304次使用
-
- go格式“占位符”输入输出 类似python的input
- 2023-01-19 346浏览
-
- Golang如何调用Python代码详解
- 2023-01-07 235浏览
-
- Go 1.27 encoding/json/v2 怎么试用:旧 API 边界、选项配置与回归核对
- 2026-08-26 195浏览
-
- Go 1.26 new 如何初始化切片与映射:类型推断、零值和迁移边界
- 2026-08-28 366浏览
-
- Go 1.26 newexpr 修复怎么落地:指针字面量替换与公共辅助函数兼容界线
- 2026-09-04 141浏览

