setup.py: restrict the allowable version of the python interpreter

Question:

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).

Asked By: gfxmonk

||

Answers:

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(...

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.

Answered By: Noah

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).

Answered By: Guy Avraham
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.