为预构建的仅C扩展模块创建Python包

jog*_*ran 10 python distutils setuptools

我想为一个不包含.py任何源文件的项目创建一个包,但是完全实现为Python C扩展(导致一个.so).另外,假设它.so已经由单独的构建过程构建(比如CMake).

我知道setuptools/distutils最低限度需要一个目录结构:

  • MyModule的
    • __init__.py

但我真正想要的是mymodule由C扩展(例如mymodule.so)提供,以便在安装包之后,import mymodule具有与直接导入相同的效果mymodule.so.

我知道我可以拥有这种目录结构:

  • MyModule的
    • __init__.py
    • mymodule_native.so

并且有__init__.py:

from mymodule_native import *
Run Code Online (Sandbox Code Playgroud)

这种作品,但从中A导入的对象mymodule实际上看起来像mymodule.mymodule_native.A.

有更直接的方式吗?

dan*_*nny 1

如果扩展是由 setuptools 配置的,则这是可能的。

例如:

from setuptools import setup, Extension

extension = Extension('mymodule', sources=[<..>])
setup('mymodule', ext_modules=[extension])
Run Code Online (Sandbox Code Playgroud)

安装后,该扩展将以import mymodule. 请注意,find_packages未使用。

这需要通过 setuptools 来完成,因为packages如果没有ext_modules提供,则需要进行设置。

然而,这使得.so模块直接安装在site-packages目录下,并且会与任何同名的非扩展 python 模块发生冲突。

这通常被认为是不好的做法,大多数库使用带有单个 的裸 Python 模块__init__.py,在该模块下可以使用扩展。

例如,您将来可能会将 python 代码添加到您的模块中,并希望将纯 python 代码与扩展代码分开。或者您可能想要添加多个扩展,这是不可能的,至少在保持相同的包名称的情况下是不可能的。

mymodule.<python modules>所以像和这样的结构mymodule.my_extension是有意义的。

就我个人而言,我会对扩展代码与 python 代码有单独的名称空间,而不是在.from <ext mod> import *__init__.py

  • 您好,谢谢您的回答。当 .so 不是由“Extension”构建时,我更感兴趣——我想唯一的方法是将其复制到模块目录中,然后以“mymodule.mymodule_native”访问它。 (2认同)