Python稳定ABI支持更多功能吗

wen python案例 2

本文目录导读:

Python稳定ABI支持更多功能吗

  1. 历史情况:稳定 ABI 为何“功能少”?
  2. 现状(Python 3.12-3.14):功能飞跃
  3. 与“完整 ABI”(非稳定)对比
  4. 实际应用建议

这是一个非常好的问题,直接关系到 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_refcntob_type 字段)直接暴露了 Python 内部的内存布局,一旦要优化垃圾回收或对象布局(Python 3.8 的借用引用优化、3.12 的 PyObject 结构体压缩),这些 API 就必须改变,因此永远不能进入稳定 ABI
  • 函数指针 vs. 宏/内联函数:很多高性能 API 是通过宏或内联函数实现的(Py_INCREFPy_DECREF),这些宏直接访问结构体成员,无法被稳定 ABI 包含,稳定 ABI 中的函数必须是真正的函数调用。

结果:早期稳定 ABI 主要包含基础的函数(如 PyLong_FromLongPyUnicode_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_CallocPyMem_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_refcntob_typeob_size,你必须使用函数(如 Py_REFCNTPy_TYPE 在稳定 ABI 中对应的函数版本是 PyObject_GetRefcntPyObject_GetType,在 3.13/3.14 中逐渐被加入,但 ob_size 等结构体偏移量仍不可靠)。
  • 某些宏/内联函数Py_INCREFPy_DECREF 在稳定 ABI 中必须通过函数调用实现(性能略低,但安全)。
  • 特定的垃圾回收 API:如 _PyUnicode_NewPyUnicode_AsStringAndSize(部分已被函数替代)。
  • 所有以 _Py 开头的内部函数:这些都是内部 API,永远不会进入稳定 ABI。
  • 灵活的缓冲区接口 Py_bufferPyBuffer_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 的方式,以获得未来的兼容性。

抱歉,评论功能暂时关闭!