我想为一个项目创建一个程序包,该程序包不包含任何.py
源文件,但已完全实现为Python C扩展(导致.so
)。另外,假设.so
已经由单独的构建过程构建(例如CMake)。
我知道setuptools/distutils至少需要一个目录结构:
但是我真正想要的是由C扩展名提供
mymodule
(例如mymodule.so
),以便安装该软件包后,import mymodule
与直接导入mymodule.so
具有相同的效果。我知道我可以拥有这种目录结构:
并将
__init__.py
为:from mymodule_native import *
这种类型的作品,但是从
A
导入的对象mymodule
实际上看起来像mymodule.mymodule_native.A
。有没有更直接的方法?
最佳答案
如果扩展是由setuptools配置的,则是可能的。
例如:
from setuptools import setup, Extension
extension = Extension('mymodule', sources=[<..>])
setup('mymodule', ext_modules=[extension])
安装后,该扩展名将以
import mymodule
的形式提供。请注意,未使用find_packages
。这需要由setuptools完成,否则,如果未提供
packages
,则将需要ext_modules
设置。但是,这使得
.so
模块直接安装在site-packages
目录下,并且将与任何同名的非扩展python模块冲突。通常认为这是不好的做法,大多数库使用带有单个
__init__.py
的裸python模块,在该模块下可以使用扩展名。例如,您将来可能会在模块中添加python代码,并希望将纯python代码与扩展代码分开。或者,您可能想要添加多个扩展名,而这是用这种方式无法实现的,至少在保持相同的程序包名称的情况下是不可能的。
因此,像
mymodule.<python modules>
和mymodule.my_extension
这样的结构是有意义的。就个人而言,我会为扩展代码和python代码分别命名空间,而不在
from <ext mod> import *
中使用__init__.py
。关于python - 为预构建的仅C扩展模块创建Python包,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45600987/