使用另一个 python 版本或另一个 OS 导入 cython 生成的 *.so 模块

Importing cython generated *.so-module with another python-version or on another OS

如何将文件 myModule.cpython-35m-x86_64-linux-gnu.so 导入 python?可能吗?

我试过常规方式:

import myModule

口译员说:

`ModuleNotFoundError: No module named 'myModule'`

这是一个我无法在我工作的集群中安装的软件,所以我只是提取了 .deb 包,它没有要安装的 wheel 文件或结构。

在另一个 Python 版本中使用为一个 Python 版本构建的 C 扩展是有问题的。通常(至少 Python3)有一种机制可以区分不同 Python 版本的 C 扩展,因此它们可以在同一目录中共存。

在您的示例中,后缀是 cpython-35m-x86_64-linux-gnu,因此此 C 扩展将由 x86_64 Linux 上的 CPython3.5 拾取。如果您尝试使用另一个 Python 版本或在另一个平台上导入此扩展,则该模块不可见并且 ModuleNotFoundError 被引发。

可以看出当前 Python 版本接受了哪些后缀,例如通过:

>>> import _imp
>>>_imp.extension_suffixes()
['.cpython-36m-x86_64-linux-gnu.so', '.abi3.so', '.so']

一种可能性是使用稳定的 C-API,它可以与多个 Python 版本一起使用而无需重新编译。 Cython 在 3.0 版本开始支持它(参见 this PR), see also this SO-post 关于 setuptools 和稳定的 C-API.

有人可能想变聪明,将扩展名重命名为简单的 .so,这样它就可以被 Finder 拾取 - 这个 can/does 适用于某些 Python 版本组合在某些平台上进行一些扩展 - 然而这种方法不能长期持续 运行 并且 不是 正确的做法。

正确的做法,是构建C扩展for/with正确的Python版本就正确OS/platform或者使用正确的轮子(或使用稳定的 C-API)。


一般来说,为 python 版本(比如说 PythonA.B)构建的 C 扩展不能被另一个 Python 版本使用(比如 PythonC.D ),因为那些 extensions/modules 链接到一个特殊的 Python 库,并且所需的功能可能 longer/not 还没有出现在另一个版本的库中。

这与 *.py 文件不同,更类似于 *.pyc 文件,不能与不同版本一起使用。

同时 PEP-3147 regulates the suffices of *.pyc-files, PEP-3149 does the same for the C-extensions. PEP-3149 is however not the state-of-the-art, as some of the problems where fixed only in Python3.5, the whole discussion can be found here.