从另一个包导入Cython标头

jra*_*amm 2 python cython python-import

我有一个名为的包A:

A/
  __init__.py
  _test.pyx
Run Code Online (Sandbox Code Playgroud)

我有另一个包的来源B:

B/
  __init__.py
  _wrapper.pxd
  _other.pxd
  _other.pyx
Run Code Online (Sandbox Code Playgroud)

_wrapper.pxd包装C库.我想cimport _wrapper.pxd参加A/_test.pyx

所以我这样做_test.pyx:

from B cimport _wrapper
Run Code Online (Sandbox Code Playgroud)

setup.py看起来像这样:

ext_modules = cythonize([
           Extension("A._test", ["src/A/_test.pyx"], include_dirs=["/path/to/B", "."])])
Run Code Online (Sandbox Code Playgroud)

当我编译时,我会B.pxd not found遇到一堆错误.

如何从另一个包中导入cython模块到我的包中?

m00*_*0am 8

简短的回答

为了从其他包中导入.pxd文件,您需要为包提供__init__.pxd文件.然后,您可以将包B视为cython包,而不必担心包含路径.

再生产

我试图像这样重现错误:

setup.py
  A/
    __init__.py
    _test.pyx
  B/
    __init__.py
    _wrapper.pxd
    _other.pxd
    _other.pyx
Run Code Online (Sandbox Code Playgroud) _wrapper.pxd
cdef inline foo():
    print("42")
Run Code Online (Sandbox Code Playgroud) _test.pyx
from B cimport _wrapper

cpdef bar():
    _wrapper.foo()
Run Code Online (Sandbox Code Playgroud) setup.py
from distutils.core import Extension, setup
from Cython.Build import cythonize

ext_modules = cythonize([
        Extension("A._test", ["A/_test.pyx"])])
setup(ext_modules=ext_modules)
Run Code Online (Sandbox Code Playgroud)

它不适用于此错误:

A/_test.pyx: cannot find cimported module 'B'
Compiling A/_test.pyx because it changed.
[1/1] Cythonizing A/_test.pyx

Error compiling Cython file:
------------------------------------------------------------
...
from B cimport _wrapper
^
------------------------------------------------------------

A/_test.pyx:1:0: 'B.pxd' not found

Error compiling Cython file:
[...]
Run Code Online (Sandbox Code Playgroud)

这应该是你所面对的.

怎么解决这个问题

对我来说,添加一个空的__init __.pxd文件解决了这个问题.我不需要指定包含路径或具有__init__.py并使用上面列出的文件.我上面没有显示的所有文件都是空的.

$ touch B/__init__.pxd

setup.py
  A/
    __init__.py
    _test.pyx
  B/
    __init__.pxd
    _wrapper.pxd
    _other.pxd
    _other.pyx

$ python setup.py build_ext --inplace
$ ipython

In [1]: from A import _test

In [2]: _test.bar()
42
Run Code Online (Sandbox Code Playgroud)

我希望这适合你.

替代

如果是一个选项,请考虑将_wrapper.pxd移动到A文件夹.然后你可以直接使用:

cimport _wrapper
Run Code Online (Sandbox Code Playgroud)

我想你想要保留包装结构,所以这只是为了完整起见.