118

I'm trying to port a python2 package to python3 (not my own) using six so that it's compatible with both. However one of the packages listed in requirements.txt is now included in the python3 stdlib and the pypi version doesn't work in python3 so I want to conditionally exclude it. Doing this in setup.py is easy, I can just do something like:

if sys.version_info[0] == 2:
    requirements += py2_requirements
else:
    requirements += py3_requirements

But I would like requirements.txt to reflect the correct list too. I can't find anything on this in the pip documentation. so does anyone know how to do it, or if it is even possible?

aquavitae
  • 17,414
  • 11
  • 63
  • 106

2 Answers2

197

You can use the environment markers to achieve this in requirements.txt since pip 6.0:

SomeProject==5.4; python_version < '2.7'
SomeProject; sys_platform == 'win32'

It is supported by setuptools too by declaring extra requirements in setup.py:

setup(
    ...
    install_requires=[
        'six',
        'humanize',
    ],
    extras_require={
        ':python_version == "2.7"': [
            'ipaddress',
        ],
    },
)

See also requirement specifiers. And Strings for the string versions of corresponding Python commands.

gene_wood
  • 1,960
  • 4
  • 26
  • 39
Jiangge Zhang
  • 4,298
  • 4
  • 25
  • 33
  • Nice! How can I do the same with `sys.platform == "win32"`? I tried using `:sys.platform == "win32"`, but I get an "Invalid environment marker" error from the `setup()` function – André Caron Apr 13 '16 at 19:32
  • 5
    Update: [PEP 496 -- Environment Markers](https://www.python.org/dev/peps/pep-0496/) has been superseded by [PEP 508 -- Dependency specification for Python Software Packages](https://www.python.org/dev/peps/pep-0508/), which fully specifies the dependency declaration syntax including the [syntax for environment markers](https://www.python.org/dev/peps/pep-0508/#environment-markers). – jkdev May 02 '17 at 20:49
  • This is great, but I feel that something has gone wrong if I need to use this? In the ideal world I guess the dependency should just itself declare that it requires Python < 2.7? Ok the OPs use case makes sense because the package actually moved location, but suppose we simply have the case that old versions don't work in Python 3. If I have control over the packages should I be going back and patching all the old versions to correctly specify their working upper Python bounds? What's the best way to handle this? – Ben Farmer Dec 10 '21 at 22:11
14

You can create multiple requirements files, put those common packages in a common file, and include them in another pip requirements file with -r file_path

requirements/
  base.txt
  python2.txt
  python3.txt

python2.txt:

-r base.txt
Django==1.4 #python2 only packages

python3.txt:

-r base.txt
Django==1.5 #python3 only packages

pip install -r requirements/python2.txt

Leonardo.Z
  • 9,425
  • 3
  • 35
  • 38