Requirements Files

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the Python Reference bibliography.

A requirements file is a list of pip install arguments, one per line, that pip reads with -r. It is not a standard: the format is defined by pip, and other tools (uv, Poetry’s export, pip-tools) read or write it because pip does. This page documents the format of pip 26.2.2. The examples were run on CPython 3.14.6 on 2026-10-22 with the birdtally-report application, whose birdtally dependency comes from the local birdwatch index (pypiserver on localhost:8080, which redirects names it does not host to PyPI).

What requirements files are for

The pip user guide names four uses:

  1. Holding the result of pip freeze, so an environment can be recreated (pip freeze > requirements.txt).

  2. Forcing a version of a sub-dependency that would otherwise be resolved differently, for example to avoid a broken release.

  3. Overriding dependency resolution by naming exact versions, for instance during an upgrade.

  4. Installing from an alternative source: a local patched copy, a VCS URL or a private index for some of the requirements.

What they are not is a place for a library’s abstract dependencies: those belong in [project] dependencies. A requirements file describes an environment, pyproject.toml describes a project; see Lock Files & Reproducible Installs.

A complete example

requirements.txt for birdtally-report:

# birdtally-report: runtime requirements (pip flavour)
--index-url ${BIRDWATCH_INDEX_URL}
--only-binary :all:

birdtally[pretty] == 0.1.0   # from the local birdwatch index
rich >= 15, \
     < 16
-c constraints.txt

constraints.txt, referenced from it:

# organisation-wide pins: only apply if something requires them
pygments == 2.21.0
markdown-it-py == 4.2.0

and requirements-dev.txt, which includes the runtime file:

-r requirements.txt
pytest >= 8
BIRDWATCH_INDEX_URL=http://localhost:8080/simple python -m pip install -r requirements-dev.txt
Looking in indexes: http://localhost:8080/simple
Collecting birdtally==0.1.0 (from birdtally[pretty]==0.1.0->-r …/requirements.txt (line 5))
  Downloading birdtally-0.1.0-py3-none-any.whl (3.7 kB)
Collecting rich<16,>=15 (from -r …/requirements.txt (line 6))
Collecting pytest>=8 (from -r requirements-dev.txt (line 2))
Collecting markdown-it-py>=2.2.0 (from rich<16,>=15->-r …/requirements.txt (line 6))
Collecting pygments<3.0.0,>=2.13.0 (from rich<16,>=15->-r …/requirements.txt (line 6))
Collecting iniconfig>=1.0.1 (from pytest>=8->-r requirements-dev.txt (line 2))
Collecting packaging>=22 (from pytest>=8->-r requirements-dev.txt (line 2))
Collecting pluggy<2,>=1.5 (from pytest>=8->-r requirements-dev.txt (line 2))
Collecting mdurl~=0.1 (from markdown-it-py>=2.2.0->rich<16,>=15->-r …/requirements.txt (line 6))
Installing collected packages: pygments, pluggy, packaging, mdurl, iniconfig, birdtally, pytest, markdown-it-py, rich

Successfully installed birdtally-0.1.0 iniconfig-2.3.1 markdown-it-py-4.2.0 mdurl-0.1.2 packaging-26.3 pluggy-1.7.0 pygments-2.21.0 pytest-9.1.1 rich-15.0.0

(The Using cached … lines are left out.) Every Collecting line names the file and line number that asked for the package, which is the quickest way to find why something is installed. The parts of the example are explained below.

Structure

  • One requirement or option per line. A requirement is anything pip install accepts as an argument: a PEP 508 specifier (rich >= 15), a local path, a URL, or -e <path-or-VCS-URL>. Spaces around operators are allowed.

  • Encoding. The file is read as UTF-8, unless it declares another encoding with a PEP 263 style comment (# -*- coding: latin-1 -*-).

  • Line continuations. A line ending in a backslash is joined with the next one, as in the rich requirement above.

  • Comments. A # at the start of a line, or after whitespace, starts a comment to the end of the line. A # without whitespace before it is part of the line, which is how URL fragments such as #subdirectory= and #sha256= survive.

  • Relative paths in -r, -c, -e and local requirements are relative to the requirements file, not to the current directory.

Supported options

Only some pip install options are allowed. Global options apply to the whole install and must be on a line of their own:

Option Notes

-i, --index-url

Replaces PyPI as the index for the whole run.

--extra-index-url

Adds an index. Every index is searched equally, which is the dependency-confusion risk described on Supply-Chain Security.

--no-index

Use only --find-links locations.

-c, --constraint

Include a constraints file; see Constraints & Build Constraints.

-r, --requirement

Include another requirements file.

-e, --editable

An editable requirement (a local project or a VCS URL).

-f, --find-links

A directory or HTML page of archives.

--no-binary, --only-binary, --prefer-binary

Wheel/sdist selection, as on the command line.

--require-hashes, --no-require-hashes

Force hash-checking mode, or (26.2) stop it from switching on automatically.

--pre, --all-releases, --only-final

Pre-release controls (the last two since 26.0).

--trusted-host

Accept a host without valid HTTPS. Avoid it.

--use-feature

Enable a feature flag for the run.

Per-requirement options go at the end of a requirement line:

  • --config-settings (-C) passes a setting to the build backend when that requirement is built from source, for example ./birdtally --config-settings editable_mode=compat; see Build System Interface;

  • --hash=sha256:… lists an allowed hash, and any line with a hash switches on hash-checking mode for the whole run; see Repeatable & Secure Installs.

An option that is not supported is a parse error that names the bad line:

printf 'rich --upgrade\n' > bad-req.txt
python -m pip install --dry-run -r bad-req.txt
ERROR: Invalid requirement: rich --upgrade
__main__.py: error: no such option: --upgrade

Nested files

-r other.txt includes another requirements file and -c constraints.txt a constraints file, both relative to the file that names them. The usual split is a runtime file and a development file that includes it, as in the example: production installs requirements.txt, developers install requirements-dev.txt and get both. Since PEP 735, the development half is better expressed as a dependency group in pyproject.toml (pip install --group dev), which Poetry and uv read as well; see Dependency Groups & Inline Script Metadata.

Environment variables

pip expands ${NAME} in a requirements file from the environment, which keeps index URLs and tokens out of the file:

--index-url https://${BIRDWATCH_USER}:${BIRDWATCH_TOKEN}@pypi.internal.example/simple
  • Only the ${NAME} form is expanded; $NAME and %NAME% are left as they are, so the same file works on every platform.

  • Use the POSIX form with braces around an upper-case name, as the documentation asks.

  • An unset variable is left as it is. With --index-url ${NOPE_UNSET} pip 26.2.2 warned The index url "${NOPE_UNSET}" seems invalid, please provide a scheme. and then failed to find any package, so a missing variable shows up as (from versions: none) rather than as a clear error.

Never commit a token in a requirements file; put it in the environment (or a keyring) and the variable in the file. See Authentication, Proxies & Certificates.

Mistakes pip warns about

Forgetting -r:

python -m pip install requirements.txt
ERROR: Could not find a version that satisfies the requirement requirements.txt (from versions: none)
HINT: You are attempting to install a package literally named "requirements.txt" (which cannot exist). Consider using the '-r' flag to install the packages listed in requirements.txt
ERROR: No matching distribution found for requirements.txt

Other classic mistakes:

  • Committing a freeze of a development machine as production requirements; it contains your tools and only your platform’s dependencies.

  • Mixing --index-url lines in several nested files. The last one read wins for the whole run, not just for the lines after it.

  • Using a requirements file as a library’s dependency list (install_requires=open("requirements.txt")…). The library then pins its users.

  • Expecting a requirements file to remove packages. pip install -r only adds and upgrades; extra packages stay. Recreate the venv, or use Poetry’s sync.

pip and Poetry

Poetry does not read requirements files. poetry export -f requirements.txt writes one from poetry.lock (with hashes and markers by default), and importing one into a Poetry project is described on Choosing & Migrating.