C API 稳定性 — Python 文档

来自菜鸟教程
Python/docs/3.10/c-api/stable
跳转至:导航、​搜索

C API 稳定性

Python 的 C API 包含在向后兼容政策 PEP 387 中。 虽然 C API 会随着每个次要版本(例如 从 3.9 到 3.10),大多数更改将与源代码兼容,通常只需添加新的 API。 更改现有 API 或删除 API 仅在弃用期或修复严重问题后进行。

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

以下划线为前缀的名称,例如 _Py_InternalState,是私有 API,即使在补丁版本中也可以在不通知的情况下更改。

稳定的应用程序二进制接口

Python 3.2 引入了 Limited API,它是 Python 的 C API 的一个子集。 仅使用 Limited API 的扩展可以编译一次并与多个 Python 版本一起使用。 受限 API 的内容在 下面列出

为了实现这一点,Python 提供了 稳定 ABI:一组将在 Python 3.x 版本之间保持兼容的符号。 稳定 ABI 包含在 Limited API 中公开的符号,但也包含其他符号 - 例如,支持旧版本 Limited API 所需的函数。

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

Py_LIMITED_API

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

Py_LIMITED_API 定义为与您的扩展支持的最低 Python 版本对应的 PY_VERSION_HEX 的值。 该扩展无需重新编译从指定版本开始的所有 Python 3 版本,并且可以使用该版本之前引入的有限 API。

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

您还可以定义 Py_LIMITED_API3。 这与 0x03020000(Python 3.2,引入有限 API 的版本)相同。

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

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

Stable ABI 中的所有函数都作为 Python 共享库中的函数出现,而不仅仅是作为宏。 这使得它们可以从不使用 C 预处理器的语言中使用。

有限的 API 范围和性能

Limited 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 或稳定 ABI 的完整保证。 Py_LIMITED_API 仅涵盖定义,但 API 还包括其他问题,例如预期语义。

Py_LIMITED_API 没有防范的一个问题是调用带有在较低 Python 版本中无效的参数的函数。 例如,考虑一个开始接受 NULL 作为参数的函数。 在 Python 3.9 中,NULL 现在选择默认行为,但在 Python 3.8 中,将直接使用该参数,导致 NULL 取消引用和崩溃。 类似的论点适用于结构域。

另一个问题是,当定义 Py_LIMITED_API 时,某些结构体字段当前并未隐藏,即使它们是 Limited API 的一部分。

出于这些原因,我们建议使用它支持的 all 次要 Python 版本测试扩展,并且最好使用 lowest 此类版本进行构建。

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

另请注意,受限 API 不一定稳定:使用 Python 3.8 使用 Py_LIMITED_API 进行编译意味着该扩展将使用 Python 3.12 运行,但不一定使用 Python 3.12 编译 。 特别是,如果稳定 ABI 保持稳定,部分受限 API 可能会被弃用和删除。


平台注意事项

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

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


受限API的内容

目前,Limited API 包括以下项目: