2016-05-26 8 views
15

Я создаю файл setup.py для проекта с некоторыми модулями расширения Cython.setup_requires с Cython?

Я уже получил эту работу:

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

setup(
    name=..., 
    ..., 
    ext_modules=cythonize([ ... ]), 
) 

Это устанавливает штраф. Однако это предполагает, что Cython установлен. Что делать, если он не установлен? Я понимаю, что это то, что параметр setup_requires для:

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

setup(
    name=..., 
    ..., 
    setup_requires=['Cython'], 
    ..., 
    ext_modules=cythonize([ ... ]), 
) 

Однако, если еще не установлен Cython, это, конечно, не в состоянии:

$ python setup.py install 
Traceback (most recent call last): 
    File "setup.py", line 2, in <module> 
    from Cython.Build import cythonize 
ImportError: No module named Cython.Build 

Что такое правильный способ сделать это? Мне нужно как-то импортировать Cython только после выполнения шага setup_requires, но мне нужно Cython, чтобы указать значения ext_modules.

ответ

4

Вы должны обернуть from Cython.Build import cythonize в try-except, и в except, определяет cythonize как фиктивные функции. Таким образом, скрипт может быть загружен без сбоев с помощью ImportError.

Затем, когда обрабатывается аргумент setup_requires, будет установлен Cython, и скрипт установки будет выполнен повторно. Так как в этот момент Cython установлен, вы сможете успешно импортировать cythonize

try: 
    from Cython.Build import cythonize 
except ImportError: 
    def cythonize(*args, **kwargs): 
     from Cython.Build import cythonize 
     return cythonize(*args, **kwargs) 

EDIT

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

+0

Это несколько Hacky, и все же, очень здорово! Не знал, что сценарий переработан, что имеет большой смысл. – Claudiu

+0

Хмм, поэтому, если я устанавливаю без установки Cython, установка работает (устанавливается Cython), но модули расширения не установлены (их нельзя импортировать из скриптов). Какие-нибудь идеи о том, что может произойти? – Claudiu

+0

Любопытный. Ах, хорошо, что он не должен быть действительно повторен. Обычно я не требую 'Cython' для установки, просто для разработки. Вместо того, чтобы создавать экземпляры 'Extension' с' cythonize', просто создавайте их непосредственно в файлах .c файлов 'Cython'. Оформить заказ в этом примере https://github.com/mobiusklein/brainpy/blob/master/setup.py – mobiusklein

17

Начиная с 18.0 выпуска setuptools (выпущено на 2015-06-23), то можно указать Cython в setup_requires и передают источники *.pyx модулей для регулярного setuptools.Extension:

from setuptools import setup, Extension 


setup(
    # ... 
    setup_requires=[ 
     # Setuptools 18.0 properly handles Cython extensions. 
     'setuptools>=18.0', 
     'cython', 
    ], 
    ext_modules=[ 
     Extension(
      'mylib', 
      sources=['src/mylib.pyx'], 
     ), 
    ], 
) 
+0

Отличный ответ, спасибо! Предпочитаете ли вы, чтобы этот подход был близок к подходу, поскольку файлы Cython скомпилированы заранее, а файлы .c используются в setup.py, а это значит, что Cython не требуется для сборки пакета? – Martinsos

+1

@Martinsos предполагает, что Cython устанавливается на всех целевых платформах с помощью setuptools (он должен, но всегда есть исключения), используя указанный подход, устраняет трудности с их созданием.c во время развертывания библиотеки, не теряя ничего, поэтому да, я бы рекомендовал этот подход. Единственное исключение, если этот процесс не работает, например. если вы нацеливаете систему с очень старыми установками setuptools, которые я бы не по умолчанию. – rutsky