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
| Requirement string | What it installs |
|---|---|
numpy |
Any version, any platform |
requests>=2.25.0,<3.0 |
requests 2.x only |
flask[async] |
flask with async extras |
pandas[excel,plot] |
pandas with multiple extras |
pywin32; sys_platform == 'win32' |
Windows only |
numpy>=1.20; python_version >= '3.9' |
Version and platform combined |
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 constrain a dependency, but they operate differently:
- Version specifier (
>=1.0,<2.0): filters which package versions are acceptable - Environment marker (
; python_version >= '3.9'): controls whether to install the dependency at all
numpy>=1.20; python_version >= '3.9' means “install numpy 1.20 or later, but only on Python 3.9+.”
Why one syntax works across tools
PEP 508 standardizes the format so pip, uv, Poetry, and Hatch all parse the same dependency strings. A project can switch tools without rewriting its dependency list.
Learn More
- PEP 508 Specification
- PEP 440: Versioning specification for version specifier syntax
- pyproject.toml reference
- pip requirements file format