What is PEP 508?
PEP 508: Dependency specification for Python Software Packages defines the standard format for declaring dependencies on Python packages. Every pyproject.toml dependency list and every pip requirement string uses PEP 508 syntax, and so does every Poetry dependency.
How a requirement string is built
A PEP 508 requirement string specifies a package name, optional version constraint, optional extras, and optional environment markers:
package-name>=1.0,<2.0; extra == 'dev' and python_version >= '3.9'The components are:
- Package name:
requests,django,numpy - Version specifier (optional):
>=1.0,==2.3.4,~=1.2.3(see PEP 440 for syntax) - Extras (optional):
[dev,test]to request optional feature bundles - Environment markers (optional):
;followed by conditions likepython_version >= '3.9'orsys_platform == 'win32'
Examples
Pure package dependency:
numpyWith version constraint:
requests>=2.25.0,<3.0With extras (install optional dependencies):
flask[async]With multiple extras:
pandas[excel,plot]With environment markers (install only on Windows):
pywin32; sys_platform == 'win32'With extras and markers:
numpy>=1.20; python_version >= '3.9' and extra == 'scientific'Environment Markers
Markers allow conditional dependencies based on the installation environment:
python_version: active Python version, e.g.'3.9','3.10'sys_platform:'linux','darwin'(macOS),'win32', etc.platform_machine: CPU architecture, e.g.'x86_64','arm64'platform_system: OS name,'Linux','Darwin', or'Windows'implementation_name: Python implementation,'cpython','pypy', etc.extra: the optional-dependency group being installed
PEP 508 also defines os_name, python_full_version, platform_release, and platform_version.
Where PEP 508 Appears
In pyproject.toml dependencies:
[project]
dependencies = [
"requests>=2.25",
"dataclasses-json; python_version < '3.7'",
"typing-extensions; python_version < '3.8'",
]
[project.optional-dependencies]
dev = [
"pytest>=6.0",
"mypy; python_version >= '3.8'",
]In requirements.txt files:
requests>=2.25
numpy>=1.20; python_version >= '3.9'pip install 'requests>=2.25,<3.0'
uv add 'numpy>=1.20; python_version >= "3.9"'Version Specifier vs. Environment Marker
Both specify constraints, but they mean different things:
- Version specifier (
>=1.0,<2.0): which package versions are acceptable - Environment marker (
python_version >= '3.9'): when to install this dependency (Python version, platform, etc.)
A single requirement can combine both:
numpy>=1.20; python_version >= '3.9'This means: “Install numpy 1.20 or later, but only on Python 3.9+. On Python 3.8, ignore this dependency entirely.”
Why one syntax works across tools
Because PEP 508 standardizes the format, pip, uv, Poetry, and Hatch all parse the same dependency strings. A project can switch tools, or use several at once, without rewriting its dependency list for each one.
Learn More
- PEP 508 Specification
- PEP 440: Versioning specification for version specifier syntax
- pyproject.toml reference
- pip requirements file format