Using PyPI’s requires‑python Field to Prevent Installation Failures
Declare the <code>requires‑python</code> field in your PyPI package to let pip reject old Python versions before installation. Learn how to set it up, test it in CI, and avoid common pitfalls.
17 Apr 2026, 09:47 UTC

Why version constraints matter when you publish a package
When a user runs pip install my‑pkg on an older Python interpreter, the package may contain syntax or API calls that simply won’t work. The classic symptom is a cryptic SyntaxError or an AttributeError that only appears at runtime. The requires‑python metadata field gives you a first‑line defense: pip can reject the install before any code runs.
What requires‑python actually does
Defined by PEP 440, requires‑python is a simple string that follows the same syntax as install_requires constraints. It declares the minimal (and optionally maximal) Python version needed for the distribution. pip reads this field from the package’s metadata (built by setuptools, poetry, etc.) and aborts installation if the current interpreter does not satisfy the specifier set.
Typical syntax
>=3.7– any 3.7 or newer interpreter.>=3.7,<4.0– restrict to the 3.x family.>=3.6,<3.9– a narrow window for a specific feature set.
When the field is missing, pip assumes the package is compatible with all Python versions the wheel format supports. That can lead to silent failures if a user installs on an unsupported interpreter.
How pip enforces the constraint
During the dependency resolution phase, pip extracts the Requires-Python header from the candidate distribution’s metadata. If the current interpreter’s sys.version_info does not match the specifier set, pip aborts with an error similar to:
ERROR: Package my-pkg requires a different Python: 3.6, but you are using 3.6.9
This pre‑emptive rejection happens before any wheel or source archive is unpacked, so no runtime errors are triggered.
Best practices for declaring and testing requires‑python
- Declare the lowest supported version. Test your package on that interpreter in CI. If it passes, you can safely include that version in the specifier.
- Use a range. A common pattern is
>=3.7,<4.0to capture all 3.x releases while excluding 4.x where breaking changes may arrive. - Combine with wheel building tools. When using
cibuildwheel, configure it to build wheels for each supported interpreter. The wheel filename will contain the Python tag (e.g.,my_pkg‑1.0‑cp37‑cp37m‑win_amd64.whl), ensuring pip selects the appropriate one. - Verify in CI. A minimal test suite can run:
This checks thatpython -m pip install --dry-run my_pkgpipwould pick a compatible distribution without actually downloading it.
Concrete example
Assume you’re publishing example_pkg that only works on Python 3.7 and newer. In pyproject.toml (using Poetry), you’d write:
[tool.poetry]
name = "example_pkg"
version = "0.1.0"
description = "A demo package"
requires-python = ">=3.7"
After building the wheel, upload it to PyPI. Now run the following tests on two interpreters:
- Python 3.6 (unsupported):
python3.6 -m pip install example_pkg # Expected output: # ERROR: Package example_pkg requires a different Python: 3.6, but you are using 3.6.9 - Python 3.8 (supported):
python3.8 -m pip install --dry-run example_pkg # Expected output: # Collecting example_pkg # Using cached example_pkg-0.1.0-py3-none-any.whl # Installing collected packages: example_pkg # Successfully installed example_pkg-0.1.0 - Verify the metadata:
python3.8 -m pip show example_pkg # Look for the line: # Requires-Python: >=3.7
These checks confirm that pip respects the constraint and would block installation on older versions.
Trade‑offs and limitations
- Older
pipversions. Pip releases prior to 20.3 do not enforcerequires‑python. Users on those versions could still install the package, potentially leading to runtime errors. The recommendation is to pin the minimum supportedpipin your documentation. - Source distributions. When a user downloads a source tarball,
requires‑pythonis not checked until the install step. If the user’s build environment is older, the install may fail mid‑process. Includingpip install --no-build-isolationin CI can surface such issues early. - Overly restrictive ranges. Declaring
>=3.7,<3.8blocks all 3.8 users, even if the code works. Always test on the lowest version first and broaden the range only if necessary.
Actionable takeaway
When you publish a Python package:
- Declare
requires‑pythonin your build metadata. - Test the constraint by installing on the lowest supported interpreter.
- Use CI to run
pip install --dry-runfor each supported wheel. - Document the minimum
pipversion needed to honor the field.
Doing so gives your users a smooth install experience and protects them from obscure runtime failures.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.