Skip to content

Instantly share code, notes, and snippets.

@xpe
Created October 27, 2025 18:19
Show Gist options
  • Save xpe/2324ab181f21985df44e1e906024fc44 to your computer and use it in GitHub Desktop.
Save xpe/2324ab181f21985df44e1e906024fc44 to your computer and use it in GitHub Desktop.
Python Package Management: A Problem-Threaded History

Python Package Management: A Problem-Threaded History

Author: Claude (Anthropic)
Date: 2025-10-27
Methodology: Content generated through web research and synthesis in response to user prompts requesting (1) three parallel histories (generous, negative, neutral) of Python package management tools from 1998-2025, then (2) a rethreading of this history by problem domain rather than chronologically. User provided the conceptual framework (spreadsheet metaphor: problems as rows, tools as columns) and iterative feedback that shaped the structure and tone.


Problem Thread: Dependency Declaration

The Problem: No standard way to say "my package needs these other packages"

  • distutils (1998-2000): No mechanism at all; users installed dependencies manually
  • setuptools (2004): Introduced install_requires in setup.py; dependencies declared but not locked
  • pip (2008): Read setuptools' dependency declarations; still no locking
  • requirements.txt (~2010): Community convention for declaring dependencies, but only direct ones
  • pipenv (2017): Introduced Pipfile with [packages] and [dev-packages] sections
  • poetry (2018): Used [tool.poetry.dependencies] in pyproject.toml
  • pyproject.toml (2016-2020): Standardized as [project.dependencies] in PEP 621
  • Status: Solved, with standard format in pyproject.toml

Problem Thread: Dependency Resolution

The Problem: No way to determine compatible versions when packages have conflicting requirements

  • distutils (1998-2000): No resolution; problem didn't exist because dependencies weren't declared
  • setuptools (2004): Resolved at install time by fetching newest versions; no conflict detection
  • pip (2008): Sequential "first wins" algorithm; silently produced incompatible environments
  • pipenv (2017): Introduced proper backtracking resolver; technically correct but extremely slow (5-15 min common)
  • poetry (2018): Used PubGrub algorithm; faster than pipenv, correct resolution
  • pip (2020): Shipped backtracking resolver in 20.3; correct but slow for complex graphs
  • uv (2024): PubGrub-based resolver in Rust; correct and fast (10-100x speedup)
  • Status: Solved technically by 2018, solved for performance by 2024

Problem Thread: Environment Isolation

The Problem: All packages installed globally, projects conflict with each other

  • distutils (1998-2000): No isolation concept; everything in site-packages
  • setuptools (2004): No isolation; made the problem worse by auto-installing dependencies globally
  • virtualenv (2007): Solved by creating isolated Python environments per project
  • pip (2008): Worked with virtualenv for isolated installs
  • pipenv (2017): Integrated virtualenv management; automatic creation and activation
  • poetry (2018): Integrated virtualenv management with configurable location
  • uv (2024): Integrated virtualenv management; very fast creation
  • Status: Solved since 2007; subsequent tools improved workflow ergonomics

Problem Thread: Uninstallation

The Problem: No way to cleanly remove packages

  • distutils (1998-2000): No uninstall mechanism
  • setuptools (2004): No uninstall mechanism; eggs could be removed manually but dependencies remained
  • pip (2008): Solved with pip uninstall command
  • Status: Solved since 2008

Problem Thread: Reproducible Builds

The Problem: Same dependency specifications produce different environments over time

  • distutils (1998-2000): Not applicable; no dependencies
  • setuptools (2004): No reproducibility; always fetched newest versions
  • pip (2008): No reproducibility without manual version pinning
  • requirements.txt (~2010): Could pin direct dependencies but not transitive ones
  • wheel (2012-2013): Binary format helped by eliminating build variation, but didn't solve dependency drift
  • pipenv (2017): Solved with Pipfile.lock containing exact versions and hashes of all dependencies
  • poetry (2018): Solved with poetry.lock containing exact versions and hashes
  • pip (2020): Still no native lock file; pip-tools required for lock file workflow
  • uv (2024): Native lock file support with uv.lock
  • Status: Solved by pipenv/poetry in 2017-2018; pip still requires external tools

Problem Thread: Build-Time Dependency Specification

The Problem: Chicken-and-egg: can't specify build tools without build tools to read specification

  • distutils (1998-2000): In stdlib, so implicitly available
  • setuptools (2004): Required setuptools to read setup.py, but setup.py declared it needed setuptools
  • pip (2008): Injected setuptools automatically; workaround, not solution
  • pyproject.toml (2016): Solved with PEP 518 [build-system] table; pip reads TOML before executing build
  • Status: Solved since 2016

Problem Thread: Installation Speed

The Problem: Installing from source is slow, especially for packages with C extensions

  • distutils (1998-2000): Always built from source
  • setuptools (2004): Eggs provided binary distribution but only for some packages
  • wheel (2012-2013): Significantly improved with binary distribution format; pip preferentially installs wheels
  • pip improvements (2014-2015): Better caching for wheels
  • pipenv (2017): Regression; dependency resolution took 5-15+ minutes
  • poetry (2018): Better than pipenv but still slower than pip for complex projects
  • pip (2020): Regression; new resolver added significant overhead for complex graphs
  • uv (2024): Dramatically improved; 10-100x faster than pip through Rust implementation and advanced caching
  • Status: Good with wheels (2013), excellent with uv (2024)

Problem Thread: Platform Fragmentation

The Problem: Need different binary packages for different Python versions, ABIs, and platforms

  • distutils (1998-2000): Built from source on each platform; slow but worked everywhere
  • setuptools (2004): Eggs were platform-specific but format was complex
  • wheel (2012-2013): Standardized platform tags; created combinatorial explosion of wheel files on PyPI
  • Status: Not solved; inherent to binary distribution. Wheels standardized but didn't eliminate the problem

Problem Thread: Workflow Fragmentation

The Problem: Need multiple separate tools for basic package management tasks

  • distutils (1998-2000): One tool, limited functionality
  • setuptools (2004): Added easy_install; now two separate tools (distutils + setuptools)
  • pip (2008): Added pip; now three tools (distutils + setuptools + pip)
  • virtualenv (2007): Added virtualenv; now four tools
  • pip-tools (2013): Added pip-compile/pip-sync; five tools
  • pipx (2018): Added tool for CLI apps; six tools
  • pipenv (2017): Attempted unification of pip + virtualenv + lock files; partial success
  • poetry (2018): Attempted unification of dependency management + building + publishing; better success
  • uv (2024): Unified pip + pip-tools + virtualenv + pipx + poetry + pyenv in one tool
  • Status: Problem worsened 1998-2018 as ecosystem added specialized tools; significantly improved with uv (2024)

Problem Thread: Configuration Fragmentation

The Problem: Multiple configuration files with overlapping purposes

  • distutils (1998-2000): setup.py only
  • setuptools (2004): Added setup.cfg as alternative; now two files
  • pip (2008): Used requirements.txt; now three file types
  • pipenv (2017): Added Pipfile and Pipfile.lock; five file types total
  • poetry (2018): Used pyproject.toml; introduced as future standard
  • pyproject.toml (2016-2020): Attempted standardization via PEP 518/621; migration ongoing
  • Status: Improving but incomplete; pyproject.toml is standard but setup.py/setup.cfg still common

Problem Thread: Lock File Transitive Dependencies

The Problem: Direct dependencies pinned but their dependencies still drift

  • distutils (1998-2000): Not applicable
  • setuptools (2004): Not addressed
  • pip (2008): Not addressed
  • requirements.txt (~2010): Could pin transitively by running pip freeze, but no distinction between direct and transitive
  • pipenv (2017): Solved with Pipfile.lock capturing full dependency tree
  • poetry (2018): Solved with poetry.lock capturing full dependency tree
  • Status: Solved by pipenv/poetry; pip still lacks native solution

Problem Thread: Dependency Resolution Correctness

The Problem: Installer produces environments where packages' dependencies aren't satisfied

  • distutils (1998-2000): Not applicable; no dependencies
  • setuptools (2004): No validation; silently created broken environments
  • pip (2008): No validation until 2020; "last wins" created incompatible sets
  • pipenv (2017): Solved with backtracking resolver that validates compatibility
  • poetry (2018): Solved with PubGrub algorithm
  • pip (2020): Solved with backtracking resolver in 20.3; broke existing workflows relying on incorrect behavior
  • uv (2024): Correct resolution from day one
  • Status: Solved since 2017, though pip took until 2020

Problem Thread: Performance of Dependency Resolution

The Problem: Determining compatible versions takes excessive time

  • distutils (1998-2000): Not applicable
  • setuptools (2004): Instant (no real resolution)
  • pip (2008): Instant (no real resolution)
  • pipenv (2017): Severe regression; 5-15 minutes common, hours for complex projects
  • poetry (2018): Better than pipenv but still slow for large projects
  • pip (2020): Slower than old pip; backtracking could take 10+ minutes
  • uv (2024): Solved with Rust implementation; typically sub-second
  • Status: Actually worsened 2017-2020 when correct resolution was introduced; fixed by uv in 2024

Problem Thread: Tool Installation and Execution

The Problem: No good way to install and run command-line tools without polluting main environment

  • distutils through pip (1998-2008): Installed globally; tools conflicted
  • virtualenv (2007): Could isolate but manual workflow
  • pipx (2018): Solved with automatic isolated environments for tools
  • uv (2024): Integrated pipx functionality with uv tool and uvx
  • Status: Solved by pipx (2018), refined by uv (2024)

Problem Thread: Python Version Management

The Problem: No unified way to install and manage multiple Python versions

  • All tools (1998-2023): Not addressed; used system Python or external tools (pyenv, homebrew, etc.)
  • uv (2024): Solved with uv python install
  • Status: Newly solved by uv; previously required separate tool

Problem Thread: Script Dependency Management

The Problem: Single-file scripts can't declare their own dependencies

  • All tools (1998-2023): Not addressed; scripts assumed environment setup separately
  • uv (2024): Solved with PEP 723 inline script metadata support
  • Status: Newly solved by uv

Emergent Patterns

  1. Recognition lag: Some problems existed for years before being recognized (e.g., lock files needed since 2004, not solved until 2017)

  2. Solution creates problem: Correct dependency resolution (2017) introduced severe performance problems, not solved until 2024

  3. Fragmentation from specialization: Each tool solving one problem created workflow fragmentation (2004-2018), finally addressed by unified tools (2024)

  4. Language barrier: Fundamental performance problems required rewriting in systems language (Rust) rather than improving Python implementation

  5. Standardization lag: pyproject.toml proposed 2016, still not universal in 2025

  6. Correctness vs. speed tradeoff: Pipenv chose correctness, sacrificed speed; uv achieved both by changing implementation language

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment