python - 构建包含多个 Cython 扩展的 Python 包

标签 python python-3.x compiler-errors cython cimport

我有以下目录结构:

testcython/
    setup.py
    testcython/
        __init__.py
        foo.pyx
        stuff.py
        bar/
            __init__.pxd
            __init__.py
            bar.pxd
            bar.pyx

其中文件内容如下:

bar.pxd

# cython: language_level=3

cdef int square(int x)

bar.pyx

# cython: language_level=3

cdef int square(int x):
    return x * x

foo.pyx

# cython: language_level=3

import cython
cimport numpy as np
import numpy as np

from .Bar cimport square

def do_square(x):
    return square(x)

stuff.py

from __future__ import print_function

from .Foo import do_square

def do():
    print(do_square(2))

setup.py

import os, sys

from Cython.Build import build_ext, cythonize
from setuptools import setup, Extension, find_packages

def ext_modules():
    import numpy as np

    include_dirs = ['.', np.get_include()]
    root_dir = os.path.abspath(os.path.dirname(__file__))
    bar_ext = Extension(
        "Bar",
        sources=[root_dir + "/testcython/bar/bar.pyx"],
        include_dirs=include_dirs,
    )
    foo_ext = Extension(
        "Foo",
        sources=[root_dir + "/testcython/foo.pyx"],
        include_dirs=include_dirs
    )
    exts = [bar_ext, foo_ext]

    return cythonize(exts)

REQUIREMENTS = [
    "numpy",
    "cython"
]

setup(
    name="testcython",
    packages=find_packages(),
    ext_package="testcython",
    ext_modules=ext_modules(),
    cmdclass={"build_ext" : build_ext},
    zip_safe=False,
    install_requires=REQUIREMENTS
)

问题

问题是,当我尝试安装此程序(在顶部 testcython 目录中使用 pip install -e .)时,我从 Cython 收到以下错误:

Complete output from command python setup.py egg_info:

    Error compiling Cython file:
    ------------------------------------------------------------
    ...

    import cython
    cimport numpy as np
    import numpy as np

    from .Bar cimport square
    ^
    ------------------------------------------------------------

    testcython/foo.pyx:7:0: relative cimport beyond main package is not allowed

    Error compiling Cython file:
    ------------------------------------------------------------
    ...
    import numpy as np

    from .Bar cimport square

    def do_square(x):
        return square(x)
              ^
    ------------------------------------------------------------

此答案 ( cython: relative cimport beyond main package is not allowed ) 意味着在 Extensioninclude_dirs 参数中包含根目录 ('.') code> 对象应该可以解决问题。

同时this part of the Cython documentation提到在使用 setuptools 包时在 setup 的参数中使用 zip_safe=False

正如您从上面的 setup.py 文件中看到的,我已经包含了这两个文件 - 但我仍然收到上面的错误。

注意:如果我更改 BarFoo 中的扩展名称(在 Extension 构造函数中)分别到 testcython.Bartestcython.Foo,然后我得到一个不同的错误:

Complete output from command python setup.py egg_info:

    Error compiling Cython file:
    ------------------------------------------------------------
    ...

    import cython
    cimport numpy as np
    import numpy as np

    from .Bar cimport square
    ^
    ------------------------------------------------------------

    testcython/foo.pyx:7:0: 'testcython/Bar/square.pxd' not found

    Error compiling Cython file:
    ------------------------------------------------------------
    ...
    import numpy as np

    from .Bar cimport square

    def do_square(x):
        return square(x)
              ^
    ------------------------------------------------------------

最佳答案

我在同事的帮助下解决了这个问题,所以我会在这里提到解决方案,以防将来对人们有所帮助。

问题与 Cython 模块的导入方式有关,更具体地说 - .so 的位置文件是在构建扩展时放置的。原来,Bar.so文件生成于 testcython目录 - 这样当尝试从 bar 导入时子模块,找不到对应的共享对象文件。

为了解决这个问题,我需要使用名称 "bar.bar"创建此扩展时,这会导致 .so文件正在生成到 testcython/bar目录。然后,在 foo.pyx ,使用 bar 中的成员模块导入必须更改为 from testcython.bar.bar cimport <name> .

注意:

此外,函数square问题中显示的不能从这种形式的另一个 Cython 模块中使用,因为没有 __pyx_capi__免费生成cdef功能。相反,这个函数必须被包装在一些 cdef 中。类作为静态方法,以便从另一个 Cython 模块使用它,即:

cdef class Square:
    @staticmethod
    cdef int square(int x)

然后就可以导入了,在 foo.pyx例如,from testcython.bar.bar cimport Square 。类(class)Square那么本质上就像一个“命名空间”。

关于python - 构建包含多个 Cython 扩展的 Python 包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56560007/

相关文章:

python - Pandas DataFrame 重新索引列问题

python - Pandas 获得最高点积的索引

python - 我如何让 mysql 在 anaconda ide (spyder) 中与 python 3.6 一起工作?

python - 如何使用 PyGithub 在存储库中创建文件?

iphone - 奇怪的CoreData编译错误

c++ - Arduino 链接未定义的引用

python - 通过 lxml etree 提取原始 XML

python-3.x - sqlite3 错误 : You did not supply a value for binding 1

python - 用 Python 读取数千个 JSON 文件的最快方法

c# - 读取Excel互操作单元格: Cannot convert mthod group 'ToString' to non-delegated type 'String' [closed]时出错