Cythonize python модули с одинаковыми именами в разных пакетах - PullRequest
2 голосов
/ 19 февраля 2020

Я использую некоторые из моих python модулей внутри проекта.

python 3.7. *
Ubuntu (разные версии в зависимости от docker образов и сред разработки)
Cython == 0.29.14

Я сталкиваюсь с проблемой, когда при наличии модулей с одинаковым именем в разных пакетах все они переносятся в. c, но компилируется только один из них с результирующим файлом .so. для одного из них .so файл создается в текущем каталоге вместо --inplace рядом с исходным файлом.

Структура папки:

    .  
    ├── my_pkg  
    │   ├── training  
    │   │   └── util.py  
    │   └── validation  
    │       └── util.py  
    └── compile.py  

compile.py выглядит следующим образом:

from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension

ext_modules = [
    Extension("*",
        ["./my_pgk/*/*.py"]
    )
]

setup(
    name="my_project",
    ext_modules=cythonize(
        ext_modules,
        compiler_directives={'language_level' : "3"}),
)

Выполнение:

python compile.py build_ext --inplace

РЕДАКТИРОВАТЬ : Глядя на (часть) журнала команд, я замечаю, что для одного Модуль .so файл фактически генерируется, но не "--inplace" вместе с исходным питоном и файлами c, а скорее в текущем каталоге. Попробовал его с более чем двумя модулями. Действительно, для всех, кроме последнего, файл .so размещен правильно, но для последнего он находится в текущем каталоге.

Вывод:

building 'my_pgk.training.utils' extension
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.7/./src/app/training/utils.o -o ./my_pgk/training/utils.cpython-37m-x86_64-linux-gnu.so

building 'utils' extension
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.7/./my_pgk/validation/utils.o -o ./utils.cpython-37m-x86_64-linux-gnu.so

Структура папки после запуска:

    .  
    ├── my_pkg  
    │   ├── training  
    │   │   ├── util.py
    │   │   ├── util.c
    │   │   └── utils.cpython-37m-x86_64-linux-gnu.so
    │   └── validation  
    │       ├── util.py
    │       └── util.c  
    ├── compile.py  
EDIT└── utils.cpython-37m-x86_64-linux-gnu.so // this is misplaced

Это приведет к созданию файла. c и .so вместе с исходным файлом .py, за исключением случаев, когда существуют модули с одинаковым именем, даже если они находятся в разных пакетах.

Я хочу иметь файлы .so для всех файлов .py, очевидно,

Я попытался перечислить их явно по имени в списке ext_modules вместо глобуса, но этого не произошло это либо.

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

Как мне указать свои модули и / или какие опции я должен включить, чтобы получить все .so файлы, сгенерированные за один прогон? Я полагаю, что я делаю что-то не так, потому что не требуется глобальная уникальность имени модуля среди всех (под) пакетов, и поэтому это должен быть поддерживаемый вариант использования.

1 Ответ

0 голосов
/ 19 февраля 2020

Глядя на код для Cythonize в репозитории Cython на GitHub, я понял, что происходит.

В основном, если используется флаг --inplace и если целевое местоположение / имя модуля не распознано в виде пакета, то есть папки, содержащей файл __init__.py[c|x|d], то Cythonize просматривает предоставленную строку целевого пути до тех пор, пока не найдет пакет или пока путь не будет «исчерпан», и в этом случае он просто сохраняет сгенерированный файл в текущем каталоге .

Итак, действительно, в одном конкретном пакете мне не хватало файла __init__.py, и поэтому .so был "неуместен". Я просто не смог распознать, что это всегда был один и тот же модуль, который выходил из строя.

Упрощенный пример, который я привел выше, не отражал реальную ситуацию, так как не было никаких файлов инициализации

...