Python C模块扩展版本不兼容吗?

时间:2020-11-02 23:33:24

标签: python cython python-c-api

我在Python 3.6中编译了python c模块扩展。它在Python 3.6环境中运作良好,但在Python 3.7和3.8环境中则无法运作,并显示错误cannot import name 'cygrpc'

我想知道这是预期的行为吗?如果是,原因是什么。

1 个答案:

答案 0 :(得分:2)

这取决于扩展的编译方式以及使用的Python C API接口。但是可以, C扩展通常必须针对特定版本的Python进行编译。在不知道如何创建扩展模块的情况下,我认为需要对其进行重新编译。

通常,Python C API会在每个发行版中进行更改。如果该更改在您的扩展程序中破坏了某些东西,自然地,您将必须为新的API接口更新扩展程序。但是,即使您所做的更改是 source-compatible (不需要更改源代码即可支持新的Python版本),这并不意味着已编译的二进制文件必须兼容。这是 Binary 界面(ABI)发挥作用的地方。

另请参见:Stable Application Binary Interface,其描述了其背后的原因:

原因主要是结构定义的演变,其中添加新字段或更改字段类型可能不会破坏API,但会破坏ABI。结果,每个Python版本[...]

都需要重新编译扩展模块。

还提到了有限的情况,其中二进制文件在各个版本之间都是兼容的:

从Python 3.2开始,已声明API的子集以确保稳定的ABI。希望使用此API的扩展模块(称为“受限API”)需要定义Py_LIMITED_API。扩展模块中隐藏了许多解释器详细信息;作为回报,将构建一个无需重新编译即可在任何3.x版本(x> = 2)上运行的模块。

因此,如果仅使用稳定API的一部分并定义Py_LIMITED_API,则编译后的模块可能会在所有Python版本之间兼容,而无需重新编译。