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

我知道setuptools/distutils至少需要一个目录结构:

  • mymodule
  • __init__.py

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

    我知道我可以拥有这种目录结构:
  • mymodule
  • __init__.py
  • mymodule_native.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/

    10-12 16:12