Использование Python setuptools, чтобы поместить скомпилированные Cython pyd-файлы в их исходные папки?
Я пытаюсь собрать пакет setup.py для моего приложения Python 3.4, которое содержит модуль Cython. Мой план состоит в том, чтобы иметь файл setup.py, который требует Cython и компилирует файл.pyx с идеей, что обычно я просто запускаю его на Win32 (x86 и x64) и Mac, а затем генерирую колеса платформы и загружаю их в PyPI, поэтому обычным пользователям не нужен Cython или что-либо компилировать.
В настоящее время я могу получить сценарий setup.py для создания файла.pyd, но он не помещает встроенный файл.pyd в то же место, что и исходный файл.pyx, где он мне нужен.
Я попытался вручную скопировать файл.pyd, но затем, когда я генерирую колесо через bdist_wheel, я получаю чистый Python wheel, который я считаю неправильным, поскольку в зависимости от платформы существуют разные версии моего встроенного файла.pyx. Я также попытался создать подкласс Distribution
класс и принуждение is_pure()
вернуть False (как описано здесь в разделе Building Wheels), но это не работает. (Все еще генерирует чистый Python wheel.)
Я предполагаю, что если я смогу заставить скрипт setup.py поместить скомпилированный файл в нужное место, то колесо не будет чистым Python, и все будет хорошо.
Итак, мои вопросы:
- Есть ли какая-то настройка в файле setup.py, чтобы указать, что скомпилированные файлы Cython должны находиться в тех же местах, что и исходные файлы?
- Или есть способ скопировать скомпилированные файлы в нужное мне место, но колесо по-прежнему должно быть не чистым?
- Или я поступаю неправильно. Должен ли я изменить свой код Python для извлечения скомпилированных пакетов из другого места? (Это не кажется мне правильным.)
- [EDIT] Или я должен поместить скомпилированный двоичный файл.pyd / .so / .dylib в пакет, добавить логику, чтобы получить правильный.pyd, основанный на архитектуре во время выполнения, и затем иметь чистый Python wheel? (Это также не кажется мне правильным.)
Больше информации о моей настройке: я использую setuptools (не distutils) в моем скрипте setup.py. Фрагмент моего setup.py находится здесь (с большим количеством материала, удаленного, чтобы сохранить его на предмет, который имеет отношение к делу):
from setuptools import setup, Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext
...
extensions = [
Extension(name='audio_interface',
sources=['mpf/mc/core/audio/audio_interface.pyx'],
include_dirs=include_dirs,
library_dirs=library_dirs,
libraries=libraries,
extra_objects=extra_objects,
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args),
...
setup(
...
ext_modules=cythonize(extensions),
cmdclass= {'build_ext': build_ext},
...
Спасибо! Брайан
2 ответа
У меня была похожая проблема, и я нашел решение, которое могло бы работать и на вас.
Из официальной документации Python для distutils.core.Extension
, name
Аргумент:
полное имя расширения, включая любые пакеты - т.е. не имя файла или путь, а имя с точками Python
Итак, если вы измените свой setup.py
чтобы:
...
extensions = [
Extension(name='mpf.mc.core.audioaudio_interface', # using dots!
sources=['mpf/mc/core/audio/audio_interface.pyx'],
include_dirs=include_dirs,
library_dirs=library_dirs,
libraries=libraries,
extra_objects=extra_objects,
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args),
...
у вас будет скомпилированный двоичный файл в том месте, которое вы хотите.
Я нашел обходной путь, который решает непосредственную проблему, которая заключается в добавлении --plat-name
к python setup.py bdist_wheel
команда. (Это было добавлено в колесе 0.27.0. Не знаю, почему оно не появилось во всех моих поисках раньше.)
Так что это решает мою проблему с помощью пункта № 2 в моем списке. Я компилирую pyx в.pyd или.so, копирую его обратно в нужное место, а затем использую --plat-name
создать платформу для конкретного колеса.
Однако мой вопрос все еще несколько остается, потому что, если мы добавим больше модулей Cython, мы скомпилируем и затем просто скопируем их все обратно в их исходные местоположения вручную, или есть ли способ их скомпилировать и автоматически перейти в их исходные местоположения? Кроме того, способ, которым я это делаю, включает два разных файла setup.py - один для компиляции и второй для установки пакета.
Поэтому я добавляю это сюда для будущих пользователей, но мои оригинальные вопросы все еще остаются.