Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standard way to declare old python versions unsupported?

Tags:

python

I want to officially drop python 2 support for a program I maintain and take full advantage of python 3 features. Instead of having a program that more-or-less works under python 2 but fails with weird behavior in corner cases, I'd like to officially break my program for python 2 with a clear "please use python 3 instead" error message. What's the most reasonable way to fail with errors for unsupported python versions?

For instance, I'd like importing the code in python 2 (at least the top-level package) to trigger an error and for my distutils setup.py script to error out when attempting to install or build it for python 2 (even when invoked via python 3 like python3 setup.py sdist_dsc --with-python2). I'd also like to include any relevant metadata to officially declare which python versions I support. There's a Requires-Python field in PEP 345 but I don't think that matters if I'm not using distutils2.

like image 767
Mu Mind Avatar asked Oct 18 '14 07:10

Mu Mind


3 Answers

As of setuptools 24.2.0 (2016-07-20) and pip 9.0.0 (2016-11-02), the python_requires argument to setup() in setup.py will tell packaging tools not to install a package that doesn't match the specifier. For example, to only support Python 3.6+:

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

To only support Python 2.7 and 3.4+:

setup(
    ...
    python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
    ...
)

Given the built-in support, the following methods in this answer should no longer be used.


To prevent importing, put this at the top of the module:

import sys

if sys.version_info[0] < 3:
    raise ImportError('Python < 3 is unsupported.')

To prevent installing, put this at the top of setup.py:

import sys

if sys.version_info[0] < 3:
    sys.exit('Python < 3 is unsupported.')

This will also fail before the check if you use syntax that is incompatible with Python 2, as the module will be parsed before running. Detecting that might be overkill for supporting "not supporting Python 2".

But I haven't actually seen this done in practice. Most maintainers just say what's supported and don't bother checking.

like image 120
davidism Avatar answered Nov 13 '22 07:11

davidism


The standard way is to set the classifiers in setup.py:

if sys.version_info < (3, 3):
    sys.exit("error: this script requires Python 3.3 or greater.")

setup(...,
classifiers=[
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
        # ... other non-version info
    ],
    ...)

For example, tulip project (asyncio) supports only Python 3.3.

You could also add in your package __init__.py:

if sys.version_info < (3, 3):
    raise ImportError("Python 3.3 or greater is required")
like image 3
jfs Avatar answered Nov 13 '22 07:11

jfs


I would go with this answer but instead I would raise an exception:

import sys

if sys.version_info[0] < 3:
    raise ImportError('Only Python 3 is supported.')
like image 2
avi Avatar answered Nov 13 '22 09:11

avi