Сборка пакета Python, содержащего несколько расширений Cython - PullRequest
0 голосов
/ 12 июня 2019

У меня следующая структура каталогов:

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
)

Вопрос

Проблема заключается в том, что, когда я пытаюсь установить это (с pip install -e . в верхнем каталоге testcython) я получаю следующие ошибки от 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: относительный cimport за пределами основного пакета не разрешен ) подразумевает, что в том числекорневой каталог ('.') в аргументе (ах) include_dirs объектов Extension должен решить проблему.

В то время как эта часть документации Cython упоминает об использовании zip_safe=False в аргументах setup при использовании пакета setuptools.

Как вы можете видетьиз моего setup.py файла выше, я включил оба из них - но я все еще получаю ошибку выше.

Примечание: Если я изменю имя расширений (в Extensionконструктор) от Bar и Foo до testcython.Bar и testcython.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)
              ^
    ------------------------------------------------------------

1 Ответ

0 голосов
/ 28 июня 2019

Я решил эту проблему с помощью коллеги, поэтому я упомяну здесь решение на случай, если оно поможет людям в будущем.

Проблема связана с тем, как импортируются модули 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.Класс Square тогда по существу действует как «пространство имен».

...