A history of Python dependency tools
A history of Python dependency tools
Python's packaging and dependency management has seen many tools rise and fall over time. This article walks through them in chronological order and notes what each tool solved, and where it fell short — based on facts.
1. Timeline
| Year | Event |
|---|---|
| 1991 | Python 0.9.0 (Guido van Rossum, February 1991). |
| 2000 | distutils included in Python 1.6's standard library. The first build/distribution standard. |
| 2003 | PyPI (Python Package Index) starts operating. Previously called "Cheese Shop". |
| 2004 | setuptools arrives. Patches distutils' limits (dependency declarations, extensibility). Bundles easy_install. |
| 2007 | virtualenv (Ian Bicking) first released. Isolated Python environments. |
| 2008 | pip (Ian Bicking and others). Aimed at fixing easy_install's pain (uninstall difficulty, etc.). |
| 2011 | The Twelve-Factor App published. Solidifies the principle of separating config and dependencies. |
| 2012 | pyenv (yyuu). Python interpreter version manager. |
| 2012 | pip becomes standard from Python 3.4 (formal in 2014). PEP 453. |
| 2012 | The venv module arrives in Python 3.3. Standard-library version of part of virtualenv. |
| 2012 | pip-tools (Vincent Driessen and others). pip-compile produces a lockfile (pinned requirements.txt). |
| 2016 | PEP 518 — introduces pyproject.toml. Standard for declaring build systems. |
| 2017 | pipenv (Kenneth Reitz). Tries an npm-like workflow with Pipfile / Pipfile.lock. |
| 2018 | Poetry (Sébastien Eustace) 1.0-pre. Unified pyproject.toml-based dependencies, builds, and publishing. |
| 2019 | PEP 517 — separates the build backend. Standard that opens up build tools beyond setuptools. |
| 2020 | PEP 621 — standard [project] section. Declares metadata in pyproject.toml. |
| 2021 | PDM (Frost Ming). Includes PEP 582 experiments. Standards-faithful. |
| 2022 | Hatch (a manager for hatchling, the build backend PyPA recommends) stabilizes after a rewrite. |
| 2024 | uv (Astral). Rust. Folds many pip / pip-tools / virtualenv / poetry workflows into one tool. |
2. virtualenv (2007)
When project A and B on the same machine need different library versions, sharing a system site-packages causes conflicts. virtualenv builds an isolated environment with its own lib/python*/site-packages per project. Python 3.3+'s python -m venv is the standard-library version of the same idea.
3. pip (2008)
easy_install was awkward to uninstall and weak at dependency resolution. pip standardized requirements.txt and imperative install / uninstall.
4. pip-tools (2012)
requirements.txt alone leaves transitive dependencies unpinned, so yesterday's build and today's build can diverge. pip-compile generates a lockfile with all transitive versions pinned, starting from abstract dependencies (requirements.in).
5. pyenv (2012)
Separates system Python from project Python. .python-version switches versions per directory automatically. The standard remedy for limits in macOS' default Python (used to be 2.7).
6. pipenv (2017)
Brought an "npm-like" Pipfile / Pipfile.lock workflow. Active for a while, but resolution speed and governance issues split adoption.
7. Poetry (2018)
Unified dependencies, metadata, and the build backend (poetry-core) inside a single pyproject.toml. Stable poetry.lock and command consistency made it the most widely adopted unified tool. Using a custom [tool.poetry] section before PEP 621 standardization later imposed migration costs for standards compliance.
8. PDM · Hatch (2021–2022)
PDM — Faithful to PEP standards. Once championed PEP 582 (__pypackages__) isolation, but settled on regular venv mode after that PEP was rejected.
Hatch — A manager paired with hatchling, the build backend PyPA recommends. Strong at managing environment matrices (per–Python-version test environments).
9. uv (2024)
Written in Rust. Provides pip / pip-tools / virtualenv compatibility modes for drop-in replacement, while also offering Poetry-style project workflows via uv add / uv sync / uv run. Pulls in the Python interpreter itself with uv python install. Emphasizes speed and integration into one tool (03-python-uv).
10. conda
Outside the line above, Anaconda / Conda (Continuum Analytics → Anaconda Inc., 2012) is a multi-language package manager that bundles C / C++ libraries and compilers alongside Python. Standard fare in scientific computing and machine learning. When NumPy / SciPy and other native dependencies are hard to build with pip, conda is the workaround.
Mambaforge / Miniforge are conda-compatible faster implementations that keep the same channel policy while improving resolution speed.
11. The same task across tools
# venv + pip
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS · Linux
source .venv/bin/activate
pip install -r requirements.txt
# pip-tools
pip-compile requirements.in
pip-sync
# Poetry
poetry add fastapi
poetry install
poetry run python -m pytest
# uv
uv add fastapi
uv sync
uv run pytest
12. Common pitfalls
Mixed traces — different tools' artifacts coexisting in the same project (requirements.txt + pyproject.toml + poetry.lock + uv.lock). Spell out which file is the SSOT in the README.
[project] vs [tool.poetry] coexisting — Poetry's own pre-1.x section and PEP 621's standard section have different intent and interpretation. Poetry 2.0+ tightens PEP 621 compatibility, but the migration is best done deliberately in one pass.
Global install on system Python — touching macOS' Apple Python or Linux' OS Python can break system tools. Use pipx or a user venv.
conda + venv activated together — PATH gets tangled and which Python wins is unclear. Activate only one.
Lockfile merge conflicts — safer to pick a side, then re-run the tool's resolution command (poetry lock, uv lock) than to merge text manually.
Closing thoughts
Python's dependency tools have flowed for 17 years from distutils → pip → virtualenv → pip-tools → pipenv → Poetry → uv. Each tool stood on the previous one's limits. Today, uv has the highest level of integration; if Poetry or pip-tools is already humming, the case to switch is weak. Just don't let two tools' traces co-exist inside one project.
Next
- regex
- git-submodule-lfs
References include the Python Packaging User Guide (PyPA), PEP 518, PEP 621, pip docs, Poetry docs, uv docs, Anaconda, pipx, and Python Packaging History (PyPA discuss).