Claudiu Claudiu - 5 months ago 45
Python Question

setup_requires with Cython?

I'm creating a

setup.py
file for a project with some Cython extension modules.

I've already gotten this to work:

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

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


This installs fine. However, this assumes Cython is installed. What if it's not installed? I understand this is what the
setup_requires
parameter is for:

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

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


However, if Cython isn't already installed, this will of course fail:

$ 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


What's the proper way to do this? I need to somehow import
Cython
only after the
setup_requires
step runs, but I need
Cython
in order to specify the
ext_modules
values.

Answer

You must wrap the from Cython.Build import cythonize in a try-except, and in the except, define cythonize as a dummy function. This way the script can be loaded without failing with an ImportError.

Then later when the setup_requires argument is handled, Cython will be installed and the setup script will be re-executed. Since at that point Cython is installed, you'll be able to successfully import cythonize

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

EDIT

As noted in comments, after setuptools deals with missing dependencies, it won't re-load Cython. I hadn't thought of it before, but you could also try a late-binding approach to stubbing out cythonize