【问题标题】:How to specify path to `.pxd` file in Cython如何在 Cython 中指定“.pxd”文件的路径
【发布时间】:2018-05-01 20:47:20
【问题描述】:

我的项目目录结构如下:

.
├── 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 的新目录。

源文件都很短,但为了避免这篇文章混乱,我将发布一个存储库的链接:https://github.com/lobachevzky/landscaping

感谢您的帮助。

【问题讨论】:

    标签: cython include-path


    【解决方案1】:

    include_dirs 用于 C/C++ 标头,而不是 Cython pxd 文件。

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

    然后要从其他模块中使用它,请通过扩展中使用的名称包括__init__.pxdcimport,例如pyx.Shrubbing,就像使用Python 模块一样。

    如果在 python 中导入(不是cimport),__init__.py 也应该包含在内。

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

    如果您想将 pxd 文件组织到单独的目录中,则将它们符号链接到模块目录中以使它们可用于模块,该目录包含 __init__.pxd.py 文件。

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

    documentation for more details

    【讨论】:

    • 我认为这是我正在寻找的答案,但是“将它们链接到模块目录中”是什么意思?这是cimport 声明还是您实际上是指符号链接?
    • @ethanabrooks 符号链接,是的。
    • 我不认为符号链接是必要的。在Cython docs 中,只要将__init__.pxd 包含在.pxd 所在的目录中,当您在实现中使用cimport .pyx 文件时,Cython 就会在您的路径中搜索定义文件。我用它来创建一些线性代数包装器,我将它们导入到项目特定的 cython 实现文件中。因此,只需确保 .pxd 文件位于路径中的目录中,例如,通过设置 PYTHONPATH
    • 根据答案,符号链接只需要If you want to organise the pxd files into separate dirs,这意味着包含__init__.pxd 的模块目录所在的位置。
    【解决方案2】:

    严格来说,这个答案比您提出的具体问题更广泛。更多的是“如何在包之间共享pxd 定义”。

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

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

    更新

    cythonemail list 提示使用zip_unsafe 安装时使用setuptools 将使一切正常。请参阅updated working exampleupdate I addeddocumentation

    【讨论】:

    • 所以,另一个回答者 danny 表示 include_dirs 用于头文件,而不是 pxd 文件。你不同意这种说法吗?
    • 如果不压缩文件,(python,cython) 的普通包含机制可以工作,不需要使用include_dirs。因此,在某种程度上,他是正确的,因为您需要手动将 dirs 添加到植根于非 zip 目录的 python 依赖项找不到的路径中。我将更新我的仓库以反映这一点。
    • 来自actual documentationThe Extension class takes many options, and a fuller explanation can be found in the distutils documentation. Some useful options to know about are include_dirs, libraries, and library_dirs which specify where to find the .h and library files when linking to external libraries.
    • 来自同一文档:Note also that if you use setuptools instead of distutils, the default action when running python setup.py install is to create a zipped egg file which will not work with cimport for pxd files when you try to use them from a dependent package. To prevent this, include zip_safe=False in the arguments to setup().
    • @danny 感谢您链接文档。我是为文档创建该补丁的人。 ;-)
    猜你喜欢
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 1970-01-01
    相关资源
    最近更新 更多