Использование 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, и все будет хорошо.

Итак, мои вопросы:

  1. Есть ли какая-то настройка в файле setup.py, чтобы указать, что скомпилированные файлы Cython должны находиться в тех же местах, что и исходные файлы?
  2. Или есть способ скопировать скомпилированные файлы в нужное мне место, но колесо по-прежнему должно быть не чистым?
  3. Или я поступаю неправильно. Должен ли я изменить свой код Python для извлечения скомпилированных пакетов из другого места? (Это не кажется мне правильным.)
  4. [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 - один для компиляции и второй для установки пакета.

Поэтому я добавляю это сюда для будущих пользователей, но мои оригинальные вопросы все еще остаются.

Другие вопросы по тегам