Search code examples
pippypi

How to make cython a requirement for a pip install?


When creating a Python package and uploading it to pypi, it will automatically install the requirements that are put in the setup.py file under install_requires, e.g.

from distutils.core import setup
setup(
  name = 'a_package',
  packages = ['a_package'],
  install_requires=['another_package']
)

When the package has a cython extension (and .pyx files instead of .c/.cpp files), the setup.py file will need to import cython to create an installable extension, e.g.

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
  name = 'a_package',
  packages = ['a_package'],
  install_requires=['another_package'],
  cmdclass = {'build_ext': build_ext},
  ext_modules = [Extension('the_extension', sources=['a_file.pyx'])]
)

But since Cython is imported before executing the setup part, when trying to install this package through pip from source (rather than from a wheel) downloaded from pypi, it will fail to install due to not being able to import cython, as it has not reached the part with the requirements yet.

I’m wondering what can be done to ensure that a pip install of this package from pypi will install cython before it tries to import it. Adding a requirements.txt with cython does not seem to add automatic-install requirements for files downloaded from pypi.

Now, I realize it’s possible to just pip install cython before pip install thispackage, but I’m wondering if there’s a better fix that would allow to install the package along with cython directly from pypi when it’s not possible to run an additional command (without resorting to uploading the .c. files and ajusting the setup.py file to use them instead of the .pyx).


Solution

  • What you're describing is a "build time dependency", and this is precisely the use case "PEP 518 -- Specifying Minimum Build System Requirements for Python Projects" was created for.

    You can specify cython as a build-time dependency by adding a pyproject.toml file like:

    [build-system]
    requires = ["cython"]
    

    Then when installing your package with a modern version of pip (or another PEP 518 compatible installer), cython will be installed into the build environment before your setup.py script is run.