requirements.txt - How to mark alternative packages
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Python's requirements.txt does not natively support "either/or" alternative packages. Each line specifies one package that must be installed. To handle alternatives (e.g., ujson or json, psycopg2 or psycopg2-binary), use extras in setup.py/pyproject.toml, environment markers, multiple requirements files, or conditional installation in a script. The standard approach for modern Python projects is to define optional dependency groups in pyproject.toml and let users choose.
Basic requirements.txt Syntax
Each line specifies one package. There is no syntax for "install A or B".
Environment Markers (Platform-Specific Alternatives)
Environment markers (PEP 508) conditionally install packages based on platform, Python version, or implementation. They handle platform-specific alternatives but not user-choice alternatives.
Multiple Requirements Files
This is the simplest way to offer alternatives. -r includes another file, so shared dependencies are not duplicated.
Optional Dependencies in pyproject.toml
This is the modern, recommended approach. Users choose which optional feature sets to install using the [extra] syntax.
Extras in setup.py (Legacy)
Conditional Installation Script
This approach tries to install the preferred package and falls back to an alternative on failure. Useful for C-extension packages that may not compile on all systems.
Using pip Constraints Files
Constraints files pin versions for packages that appear in requirements.txt but do not force their installation. They are useful for locking versions in CI/CD without changing the requirements file.
Common Pitfalls
- Expecting
requirements.txtto support OR syntax: There is noA | BorA or Bsyntax in requirements.txt. Each line installs exactly one package. Use multiple requirements files,pyproject.tomlextras, or an install script for alternatives. - Using
psycopg2in requirements whenpsycopg2-binaryis easier:psycopg2requireslibpq-devand a C compiler to build from source.psycopg2-binaryincludes pre-built binaries. For development and CI, use-binary; for production, compile from source. Offer both as alternatives. - Forgetting environment markers syntax: Markers use
==for comparison, not=. Valid markers includesys_platform,python_version,implementation_name, andos_name. An invalid marker silently does nothing. - Not using
-rto include base files: Duplicating shared dependencies acrossrequirements-postgres.txtandrequirements-mysql.txtleads to version drift. Use-r requirements-base.txtto include shared dependencies from one place. - Mixing
pyproject.tomlandsetup.pyfor extras: Having optional dependencies defined in bothpyproject.tomlandsetup.pycauses confusion about which takes precedence. Usepyproject.tomlfor new projects;setup.pyonly for backward compatibility.
Summary
requirements.txtdoes not support alternative/OR package syntax — each line installs one package- Use multiple requirements files (
-r base.txt) to offer database, cache, or feature alternatives - Use
[project.optional-dependencies]inpyproject.tomlfor the modern approach withpip install myapp[extra] - Use environment markers (
; sys_platform == "win32") for platform-specific packages - Use a conditional install script for try-first/fallback patterns (e.g., C extension vs pure Python)
- Constraints files (
-c constraints.txt) pin versions without requiring installation

