如何在 Cython 中指定 .pxd 文件的路径

How to specify path to `.pxd` file in Cython

我的项目有以下目录结构:

.
├── Makefile
├── pxd
├── pyx
│   ├── Landscaping.pyx
│   ├── Shrubbing.pxd
│   └── Shrubbing.pyx
└── setup.py

但是,如果我将 Shrubbing.pxd 移动到其他任何地方,例如 pxd/,我会收到以下错误:

Error compiling Cython file:
------------------------------------------------------------
...
import pyx.Shrubbing
cimport Shrubbing
       ^
------------------------------------------------------------

pyx/Landscaping.pyx:2:8: 'Shrubbing.pxd' not found

Error compiling Cython file:
------------------------------------------------------------
...
import pyx.Shrubbing
cimport Shrubbing

cdef Shrubbing.Shrubbery sh
    ^
------------------------------------------------------------

这很奇怪,因为在 setup.py 我有:

from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(ext_modules=cythonize([
    Extension(
        'pyx.Landscaping',
        sources=["pyx/Landscaping.pyx"],
        include_dirs=['pxd']), # <-- HERE
    Extension('pyx.Shrubbing', sources=["pyx/Shrubbing.pyx"])
]))

这清楚地指定了 Shrubbing.pxd 的新目录。

源文件都很短,但为了避免混乱 post,我将 post 一个 link 到存储库:https://github.com/lobachevzky/landscaping

感谢您的帮助。

include_dirs 适用于 C/C++ headers,不适用于 Cython pxd 文件。

一般来说,最好将相关的 pyx/pxd 文件放在同一个目录中,即 Shrubbing.pyx 和 Shrubbing.pxd 应该在同一个目录中。

然后使用 其他模块 中的那个,通过扩展中使用的名称包含 __init__.pxdcimport,例如 pyx.Shrubbing就像使用 Python 模块一样。

如果在 python(而不是 cimport)中导入,则还应包括 __init__.py

在同一模块 OTOH 中使用时,.pxd 需要在该模块的运行时可用,这意味着将其包含在 Python 中搜索路径。

如果你想将 pxd 文件组织到单独的目录中,然后 link 它们在模块目录中象征性地使它们对模块可用,目录包含 __init__.pxd.py 文件。

这有点混乱,因为 Cython 目前不支持相对导入,因此当想要从另一个目录导入时需要 linking。

documentation for more details

严格来说,这个答案比您提出的具体问题更广泛。更 "how do you share pxd definitions between packages".

为了自己解决这个问题,我创建了一个 cython_example 存储库。它并不令人满意,因为它使用旧的 distutils 工具而不是 setuptools 来防止 zip/egg 封装底层文件,但这里可能会有所启发。我正在积极寻找可以从 egg 文件中自动提取代码的改进,以便可以使用 setuptools

核心思想是利用os.path.dirname(from_package.__file__)来添加到include路径。请参阅 setup.py 文件。

更新:

cython email list provided the hint that using zip_unsafe when installing using setuptools would make everything work. See the updated working example and the update I added to the documentation .