【问题标题】:Python can't import extensions generated in a nested hierarchyPython 无法导入嵌套层次结构中生成的扩展
【发布时间】:2017-12-21 11:08:39
【问题描述】:

我有一个具有深度嵌套模块层次结构的库,其结构类似于

src/
  my_library/
    __init__.py
    my_module/
      __init__.py
      my_submodule.py

例如一个人可能可以写from my_library.my_module.my_submodule import Foo等。

我有一个遍历文件树的函数,发现所有 python 模块并将它们转换为Extension 传递给cythonize 的对象,有效地对整个模块进行cythonize。在构建之前检查它们,它们看起来(以字典形式)类似于:

(Pdb) pp vars(e)
{'define_macros': [],
 'depends': [],
 'export_symbols': [],
 'extra_compile_args': [],
 'extra_link_args': [],
 'extra_objects': [],
 'include_dirs': [],
 'language': None,
 'libraries': [],
 'library_dirs': [],
 'name': 'my_library.my_module.my_submodule',
 'optional': None,
 'runtime_library_dirs': [],
 'sources': ['src/my_library/my_module/my_submodule.c'],
 'swig_opts': [],
 'undef_macros': []}

然后将扩展列表传递给setuptools.setup() 的ext_modules 参数。调用setup.py install 会按预期产生一堆编译,这很棒。但是,文件在编译之前被写入一个目录结构,镜像它们的位置,所以例如它最终会出现类似

lib/python3.4/site-packages/
  my_library.cpython-34m.so
  my_library/
    my_module.cpython-34m.so
    my_module/
      my_submodule.cpython-34m.so

由于这种嵌套结构,我只能在安装目录位于我的PYTHONPATH 中时导入顶级对象:

>>> import my_library
>>> my_library.foo()
'foo'
>>> import my_library.my_module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'my_library.my_module'

似乎由于生成的文件被写入子目录而不是直接写入site-packages 文件夹,python 解释器无法发现它们。我对python扩展了解不多,但是环顾四周,我没有看到让python将它们放在平面结构中而不是嵌套的方法,也不知道是否有办法让python发现.so写入子目录的文件——也许通过添加 __init__.py 文件?

【问题讨论】:

    标签: python cython setuptools


    【解决方案1】:

    看起来您“双重定义”my_library:一次通过 __init__.py 文件,一次通过 cython 代码。

    解决方案是拥有一个“纯 Python”模块层次结构,并在与 Python 模块的任何冲突之外创建 cython 模块作为该层次结构中的元素。

    src/   
        my_library/
            __init__.py
            my_first_cython_module.pyx
            my_module/
                __init__.py
                my_submodule.py
                other_cython_module.pyx
    

    这样,你可以做import my_library.my_module等。对于Cython模块,导入my_library.my_first_cython_module等。

    您可以通过从 __init__.py 文件中导入 Cython 代码来保留当前的导入名称:

    from my_library.my_first_cython_module import foo
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多