C API 稳定性

除非另有说明,Python 的 C API 受 PEP 387 反向兼容性策略的覆盖。对其进行的大多数更改都是源代码兼容的(通常仅通过添加新的 API)。更改现有 API 或删除 API 仅在弃用期过后或为修复严重问题时才进行。

CPython 的应用二进制接口(ABI)在次要版本之间是向前和向后兼容的(如果它们以相同的方式编译;请参阅下面的平台注意事项)。因此,为 Python 3.10.0 编译的代码将在 3.10.8 上运行,反之亦然,但需要针对 3.9.x 和 3.11.x 分别编译。

C API 有两个级别,具有不同的稳定性预期:

  • 不稳定 API,可能会在次要版本中更改,而无需弃用期。它在名称中以 PyUnstable 前缀标记。

  • 有限 API,在多个次要版本之间兼容。当定义了 Py_LIMITED_API 时,只有这个子集从 Python.h 中暴露出来。

下面将更详细地讨论这些内容。

以下划线为前缀的名称,例如 _Py_InternalState,是私有 API,即使在补丁版本中也可能在不通知的情况下更改。如果您需要使用此 API,请考虑联系 CPython 开发者,讨论为您的用例添加公共 API。

不稳定 C API

任何以 PyUnstable 前缀命名的 API 都会暴露 CPython 的实现细节,并且可能在每个次要版本(例如从 3.9 到 3.10)中更改,而不会有任何弃用警告。但是,它不会在错误修复版本(例如从 3.10.0 到 3.10.1)中更改。

它通常用于调试器等专门的低级工具。

使用此 API 的项目需要关注 CPython 的开发并投入额外精力来适应更改。

稳定应用二进制接口

为简单起见,本文档讨论**扩展**,但有限 API 和稳定 ABI 对于所有 API 用途(例如嵌入 Python)都以相同的方式工作。

有限 C API

Python 3.2 引入了**有限 API**,它是 Python C API 的一个子集。仅使用有限 API 的扩展可以编译一次,并在多个 Python 版本上加载。有限 API 的内容如下所示

Py_LIMITED_API

在包含 Python.h 之前定义此宏,以选择仅使用有限 API,并选择有限 API 版本。

Py_LIMITED_API 定义为与您的扩展支持的最低 Python 版本对应的 PY_VERSION_HEX 值。该扩展将与从指定版本开始的所有 Python 3 版本兼容 ABI,并且可以使用在该版本之前引入的有限 API。

不要直接使用 PY_VERSION_HEX 宏,而是硬编码一个最小次要版本(例如,Python 3.10 的 0x030A0000),以便在未来 Python 版本编译时保持稳定性。

您还可以将 Py_LIMITED_API 定义为 3。这与 0x03020000(Python 3.2,引入有限 API 的版本)具有相同的功能。

稳定 ABI

为了实现这一点,Python 提供了一个**稳定 ABI**:一组在 Python 3.x 版本之间保持 ABI 兼容性的符号。

备注

稳定 ABI 防止了 ABI 问题,例如由于缺少符号而导致的链接器错误,或由于结构布局或函数签名更改而导致的数据损坏。但是,Python 中的其他更改可能会改变扩展的**行为**。有关详细信息,请参阅 Python 的反向兼容性策略(PEP 387)。

稳定 ABI 包含在有限 API中公开的符号,但也包含其他符号——例如,支持旧版有限 API 所需的函数。

在 Windows 上,使用稳定 ABI 的扩展应该链接到 python3.dll,而不是特定于版本的库,例如 python39.dll

在某些平台上,Python 会查找并加载带有 abi3 标签的共享库文件(例如 mymodule.abi3.so)。它不检查此类扩展是否符合稳定 ABI。用户(或其打包工具)需要确保,例如,用 3.10+ 有限 API 构建的扩展不会安装到较低版本的 Python 上。

稳定 ABI 中的所有函数都以函数的身份存在于 Python 的共享库中,而不仅仅是宏。这使得它们可以从不使用 C 预处理器的语言中使用。

有限 API 范围和性能

有限 API 的目标是允许使用完整的 C API 所能实现的一切,但可能会牺牲一些性能。

例如,PyList_GetItem() 可用,但其“不安全”的宏变体 PyList_GET_ITEM() 不可用。该宏可能更快,因为它依赖于列表对象的特定版本实现细节。

如果没有定义 Py_LIMITED_API,一些 C API 函数会被内联或替换为宏。定义 Py_LIMITED_API 会禁用此内联,从而在 Python 数据结构改进时保持稳定性,但可能会降低性能。

通过省略 Py_LIMITED_API 定义,可以用特定于版本的 ABI 编译有限 API 扩展。这可以提高该 Python 版本的性能,但会限制兼容性。使用 Py_LIMITED_API 编译将生成一个扩展,该扩展可以在没有特定版本扩展的情况下进行分发——例如,用于即将推出的 Python 版本的预发布版本。

有限 API 注意事项

请注意,使用 Py_LIMITED_API 进行编译**并不能**完全保证代码符合有限 API稳定 ABIPy_LIMITED_API 仅涵盖定义,但 API 还包括其他问题,例如预期语义。

一个 Py_LIMITED_API 未能防范的问题是,在较低的 Python 版本中,使用无效参数调用函数。例如,考虑一个函数开始接受 NULL 作为参数的情况。在 Python 3.9 中,NULL 现在选择默认行为,但在 Python 3.8 中,参数将直接使用,导致 NULL 解引用和崩溃。类似的参数也适用于结构体字段。

另一个问题是,即使定义了 Py_LIMITED_API,某些结构体字段目前也未被隐藏,尽管它们是有限 API 的一部分。

基于这些原因,我们建议使用其支持的所有次要 Python 版本来测试扩展,最好使用**最低**版本进行构建。

我们还建议查阅所有使用的 API 文档,以检查它是否明确属于有限 API。即使定义了 Py_LIMITED_API,出于技术原因(甚至无意中,作为错误),一些私有声明也会暴露出来。

另请注意,有限 API 不一定稳定:使用 Python 3.8 编译 Py_LIMITED_API 意味着该扩展将与 Python 3.12 一起运行,但它不一定与 Python 3.12 **编译**。特别是,有限 API 的某些部分可能会被弃用和删除,前提是稳定 ABI 保持稳定。

平台注意事项

ABI 稳定性不仅取决于 Python,还取决于所使用的编译器、低级库和编译器选项。就稳定 ABI而言,这些细节定义了一个“平台”。它们通常取决于操作系统类型和处理器架构。

每个 Python 分发商都有责任确保在特定平台上构建所有 Python 版本的方式不会破坏稳定 ABI。 python.org 的 Windows 和 macOS 版本以及许多第三方分发商都符合这种情况。

有限 API 的内容

目前,有限 API 包括以下项目: