setup.py: restrict the allowable version of the python interpreter
Asked Answered
A

3

37

I have a Python library. Unfortunately I have not updated it to work with Python 3 yet.

In its setup.py, I added

install_requires=['python<3'],

My intent was to not allow this package to be installed/used under Python 3, because I know it doesn't (yet) work. I don't think this is the right way to do it, because pip then tries to download and install python 2.7.3 (which is already the installed version!).

How should I specify my library dependency on a particular range of Python interpreter versions? Should I add a Programming Language :: Python :: 2 :: Only tag? Will this actually prevent installation under Python 3? What if I also want to restrict the minimum version to Python 2.6?

I'd prefer a solution that works everywhere, but would settle for one that only works in pip (and hopefully doesn't cause easy_install to choke).

Aesthetic answered 18/12, 2012 at 1:19 Comment(2)
Answered here: #13385837Nealy
Relevant: packaging.python.org/guides/…, which mentions that "Although the list of classifiers is often used to declare what Python versions a project supports, this information is only used for searching & browsing projects on PyPI, not for installing projects. To actually restrict what Python versions a project can be installed on, use the python_requires argument."Bussard
T
38

As of version 9.0.1 pip will honor a new python_requires string, specifying the Python version required for installation, e.g, for example if one wishes to enforce minimum Python version of 3.3:

setup(
    ...,
    python_requires=">=3.3"
)

See here for more details. See also this answer on SO.

Taught answered 27/7, 2017 at 23:10 Comment(3)
I think it is worth editing the answer to include the fact that the project MUST be installed using pip3 install [-e] as it mentioned in the first link you provided.Foredo
@GuyAvraham Could you clarify your comment? pip2 install should honor this as well if it's a recent enough version of pip (as far as I can tell, pip 9.0 is compatible back to python 2.6).Taught
I added an answer to elaborate on this.Foredo
A
19

A possible solution is to test for the Python version, since pip can't satisfy the Python version except for the version it's currently running in (it installs in the current Python environment):

import sys
if not sys.version_info[0] == 2:
    sys.exit("Sorry, Python 3 is not supported (yet)")

setup(...
Ahola answered 18/12, 2012 at 1:53 Comment(2)
True, that would work. It'd be much nicer to have something built into the dependencies though, so that pip would know up-front not to bother downloading and running the installer.Aesthetic
Why not both? Your answer is what one should not do but rather rely on the builtin features, although using this answer additionally to the python_requires would be great! You may update that?Tashia
F
4

After commenting in the answer above and receiving feedback, I thought to turn my comment into an answer. Note that the answers above are all fine, yet from my experience, I found one thing that is "missing" in these answers, that needs to be pointed out, so here I will illustrate this issue.

For simplicity and completeness of illustration, I have composed a very minimal and simple Python 3 project. The only 3rd party package it uses, is the famous SSH client package paramiko (it's official PyPi page can be found here).

The Python interpreter in the virtual environment of my project is of version 3.6.9

Now, in order to check the python_requires attribute "in action", I have added it to the project's setup.py script, which looks as follows:

from setuptools import setup, find_packages

setup(name='mySampleProject',
      version='1.0',
      description='Sample project in Python 3',
      author='Guy Avraham',
      license='MIT',
      packages=find_packages(),
      include_package_data=True,
      python_requires='>=3.8',
      install_requires=['paramiko'])

Note that I "required" that the Python version will be 3.8+. This of course should NOT work with the current Python version in the project's virtual environment which is 3.6.9.

Now, when I build the project using the "normal" use in the setup.py, meaning by running: python3 setup.py install, the project was built successfully. See the following output of the pip3 list command after running the python3 setup.py install command:

(mySampleProject_env) guya@ubuntu:~/mySampleProject$ pip3 list
DEPRECATION: The default format will switch to columns in the future. You can use -- 
format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
bcrypt (3.2.0)
cffi (1.14.3)
cryptography (3.1.1)
mySampleProject (1.0)
paramiko (2.7.2)
pip (9.0.1)
pkg-resources (0.0.0)
pycparser (2.20)
PyNaCl (1.4.0)
setuptools (39.0.1)
six (1.15.0)

As you can see, the project, along with all its "sub dependencies" was installed EVEN though I was NOT expecting it to.

On the other hand, when I installed the project using the command: pip3 install -e . (note the . to indicate the "current working directory"), I got the following output:

(mySampleProject_env) guya@ubuntu:~/mySampleProject$ pip3 install -e .
Obtaining file:///home/guya/mySampleProject
mySampleProject requires Python '>=3.8' but the running Python is 3.6.9

Which now, indeed, "considers" the python_requires attribute, thus "failing" the build of the project.

It is detailed in the very first paragraph in the tutorial in this page and also during minutes ~09:00 - 11:00 in this video

NOTE: I did NOT check all the above for Python 2 (or pip for Python 2).

Foredo answered 16/10, 2020 at 9:20 Comment(2)
I think this is because you have an old version of setuptools with your python 3.6.9. If you pip install -U setuptools I'm guessing it will honor the python_requires argument. Awkward that this functionality is relatively recent, because it's most needed with the old versions of python!Taught
@Taught - I tried what you have suggested: Created virtual environment using venv with Python 3.8.5 (Ubuntu 20.04 Desktop). The setuptools version was 44.0.0. Upgraded the setuptools as you suggested to version 50.3.2, performed installation using the "normal setup.py install" (i.e. - python3 setup.py install), yet the python_requires "attribute" was still not taking into consideration (i.e. - the project was installed successfully, even though the Python version is 3.8.5 and I asked for >=3.9). When I did it with the command pip3 install -e ., the installation failed (as required).Foredo

© 2022 - 2024 — McMap. All rights reserved.