本文目录导读:

这是一个非常好的问题,直接关系到 Python C 扩展的兼容性和未来发展方向。
简短回答:是的,Python 稳定 ABI 正在持续支持更多功能,尤其是在 Python 3.12 和 3.13 中,新增了非常多重要的 API,使其实用性大大增强。
但需要先澄清一个核心概念:“稳定 ABI” 的目的是让用 C 写的扩展模块,在不重新编译的情况下,能兼容未来的多个 Python 小版本(3.11、3.12、3.13...)。 它并不是一个功能更少、受限的版本,而是一个经过精心挑选、保证向后兼容的公共 API 子集。
下面来详细解释“更多功能”具体体现在哪里,以及现状如何。
历史情况:稳定 ABI 为何“功能少”?
在 Python 3.2 引入稳定 ABI 后的很长一段时间里(直到 3.10 左右),它的功能确实非常有限,原因是:
- 核心原则:稳定 ABI 只包含那些 Python 开发团队能够承诺在未来版本中完全不改变其行为、布局和签名的 API。
- 内部结构暴露:早期大量的核心 API(如直接访问
PyObject的结构体ob_refcnt、ob_type字段)直接暴露了 Python 内部的内存布局,一旦要优化垃圾回收或对象布局(Python 3.8 的借用引用优化、3.12 的PyObject结构体压缩),这些 API 就必须改变,因此永远不能进入稳定 ABI。 - 函数指针 vs. 宏/内联函数:很多高性能 API 是通过宏或内联函数实现的(
Py_INCREF、Py_DECREF),这些宏直接访问结构体成员,无法被稳定 ABI 包含,稳定 ABI 中的函数必须是真正的函数调用。
结果:早期稳定 ABI 主要包含基础的函数(如 PyLong_FromLong、PyUnicode_FromString),但缺失了:
- 直接的对象类型检查(
PyList_Check是宏,不可用) - 高效的内存对象管理(
PyMem_*家族) - 关键的抽象协议(如迭代器、序列、映射接口)
这让很多复杂的扩展被迫选择不兼容(即只打包针对特定 Python 版本的 .so 文件)以获得完整功能。
现状(Python 3.12-3.14):功能飞跃
从 Python 3.12 开始,CPython 核心团队(特别是 Barry Warsaw、Łukasz Langa 等人)发起了一个积极推广和扩充稳定 ABI 的计划,新增的功能主要包含:
核心新增功能
| 功能类别 | 新增 API 示例 | Python 版本 | 意义 |
|---|---|---|---|
| 对象类型 | PyType_FromModuleAndSpec |
12 | 无需定义 PyTypeObject 静态结构体,完全通过 C3 风格创建类型,这是最重要的新增。 |
| 抽象协议 | PyObject_GenericGetDict |
12 | 实现了属性字典获取的通用方法,常用于元类。 |
| 内存管理 | PyMem_Calloc, PyMem_RawMalloc |
12 | 提供更安全的内存分配方式,与 C 标准库 calloc 对应。 |
| 模块创建 | PyModule_AddObjectRef |
12 | 比 PyModule_AddObject 更安全,自动管理引用计数。 |
| 异常处理 | PyErr_FormatV |
12 | 格式化异常信息的变参版本。 |
| 弱引用 | PyWeakref_GetRef |
13 | 安全地从弱引用获取强引用,避免竞态条件。 |
最重要的新增:PyType_FromModuleAndSpec
这是 Python 3.12 稳定 ABI 的最重大功能,它允许你完全通过一个 PyType_Spec 结构体来动态定义并创建类型,而不是使用传统的、依赖于内部 PyTypeObject 布局的静态定义方式。
在 3.12 之前,即使你使用稳定 ABI,创建自定义类型通常也是受限的(或者需要依赖于某些未进入稳定 ABI 的细节)。PyType_FromModuleAndSpec 的出现,使得用稳定 ABI 编写包含自定义对象+方法的扩展成为切实可行。
与“完整 ABI”(非稳定)对比
即便新增了这么多,稳定 ABI 截至 Python 3.13)依然无法支持的部分:
- 直接访问对象内部结构:不能直接读
ob_refcnt、ob_type、ob_size,你必须使用函数(如Py_REFCNT、Py_TYPE在稳定 ABI 中对应的函数版本是PyObject_GetRefcnt、PyObject_GetType,在 3.13/3.14 中逐渐被加入,但ob_size等结构体偏移量仍不可靠)。 - 某些宏/内联函数:
Py_INCREF、Py_DECREF在稳定 ABI 中必须通过函数调用实现(性能略低,但安全)。 - 特定的垃圾回收 API:如
_PyUnicode_New、PyUnicode_AsStringAndSize(部分已被函数替代)。 - 所有以
_Py开头的内部函数:这些都是内部 API,永远不会进入稳定 ABI。 - 灵活的缓冲区接口
Py_buffer:PyBuffer_FillInfo等核心函数在稳定 ABI 中可用,但完整的缓冲协议(如自定义tp_as_buffer中的bf_getbuffer函数)在某些场景下仍需小心编写。
实际应用建议
现在是否值得使用稳定 ABI?
- 绝对值得,尤其对于分发包:如果你分发一个
.whl文件,希望它能在用户的 Python 3.12、3.13、3.14 上直接运行(无需用户编译),那么必须使用稳定 ABI,否则你只能编译多个特定版本的.so文件。 - 对于高性能库:如果你的库极度依赖直接访问对象结构体(NumPy、Pandas 的部分核心代码),那么稳定 ABI 仍然有性能限制,但这类核心库通常已经做了大量优化,CPython 核心团队在 3.12 中通过
PyType_FromModuleAndSpec等方式,已经大幅缩小了性能差距。 - 对于大多数普通扩展:90% 的功能现在都可通过稳定 ABI 实现,甚至复杂的 Python 对象(如自定义容器、类装饰器、异步生成器)也已支持。
| 特性 | 早期稳定 ABI(<3.11) | 现代稳定 ABI(>=3.12) |
|---|---|---|
| 支持的功能 | 非常有限(基本类型操作、模块创建) | 大幅扩展(自定义类型、异常、抽象协议、内存管理) |
| 类型创建 | 不完整,依赖内部结构 | 完整支持(PyType_FromModuleAndSpec) |
| 性能 | 因为缺失函数,有时需要绕过 | 与完整 ABI 相当(除开必要的函数调用开销) |
| 主流库采用 | 极少 | 开始成为主流(如 cryptography、cffi、部分 numpy 组件) |
| 未来趋势 | 停滞 | 积极扩充中,预计会逐步覆盖更多领域 |
是的,Python 稳定 ABI 正在非常积极地支持更多功能,并且已从“功能受限”转变为“功能相当完整的兼容层”,对于新编写的 C 扩展,强烈建议使用稳定 ABI + PyType_FromModuleAndSpec 的方式,以获得未来的兼容性。