skip to content
Logo Joseph Joyal

Why We Chose PDM Over Poetry, Pip, and UV for Python

/

TL;DR:

Our team was about to start a new Python project. Normally, we’d use the standard requirements.txt approach, but we wanted to try more modern tools for managing Python dependencies—similar to how Node.js uses npm and package.json. Although ‘uv’ is the fastest option compared to Poetry and PDM, we picked PDM because it’s simple and lets us run single-file scripts easily (like pdm run start runs python example.py). With ‘uv’, you have to specify a function inside a file (e.g., uv run start runs python example:main). If our project grows and package installation speed becomes more important, switching from PDM to uv will be easy.


The Problem: Why requirements.txt Wasn’t Enough

We’d always used pip and requirements.txt for dependency management. But as our projects grew, so did the headaches:

  • No project metadata: requirements.txt only lists dependencies, not project details like name, version, or author.
  • No lock file: Dependency versions could drift, causing “works on my machine” issues.
  • Manual environment management: Creating and activating virtual environments was tedious and error-prone.
  • No support for modern standards: pip and requirements.txt don’t natively support PEP 517/518/621.

Exploring Alternatives: Poetry, uv, and PDM

We researched modern tools that promised to solve these problems:

  • Poetry: Popular, feature-rich, but sometimes slow and opinionated about project structure.
  • uv: Blazing fast installer and resolver, but focused mainly on speed and less on project management.
  • PDM: Standards-based, lightweight, and designed to feel like npm for Python.

After testing all three, we chose PDM for its balance of simplicity, standards compliance, and developer experience.


Why PDM? Advantages Over pip+requirements.txt

PDM stood out for several reasons:

  • Uses pyproject.toml: All project metadata and dependencies in one file, following modern Python standards.
  • Automatic virtual environments: No more manual setup—PDM handles it for you.
  • Lock file (pdm.lock): Ensures reproducible installs across machines.
  • Editable installs: Perfect for development workflows.
  • User-friendly CLI: Commands like pdm add, pdm run, and pdm update are intuitive and similar to npm.

PDM vs. Poetry and uv: Why We Chose PDM

FeaturePDMPoetryuv
Standards-basedYes (pyproject.toml)Yes (pyproject.toml)Yes (pyproject.toml)
Virtual env mgmtAutomaticAutomaticAutomatic
Lock fileYes (pdm.lock)Yes (poetry.lock)Yes (uv.lock)
Editable installsYesYesYes
CLI experiencenpm-like, simpleRich, but opinionatedFast, minimal
SpeedFastModerateVery fast
Ecosystem adoptionGrowingWidely adoptedGrowing Very Fast

Getting Started: Setting Up PDM

PDM works best when installed via pipx to avoid global package conflicts.

Terminal window
python3 -m pip install --user pipx
python3 -m pipx ensurepath

Step 2: Install PDM

Terminal window
pipx install pdm

Step 3: Initialize Your Project

Terminal window
mkdir pdm-ref-project
cd pdm-ref-project
pdm init
  • Answer the prompts to set up your project metadata and dependencies.

Step 4: Add Dependencies

Terminal window
pdm add requests

Step 5: Run Your Code

Terminal window
pdm run python main.py

Real-World Impact

After switching to PDM, our team noticed:

  • Fewer conflicts: Lock files and isolated environments kept dependencies consistent.
  • Faster onboarding: New team members could set up projects with a single command.
  • Better standards compliance: Our projects were future-proof and compatible with modern Python tooling.

Conclusion

Modern Python package managers like PDM, Poetry, and uv solve many pain points of traditional workflows. For our team, PDM offered the right mix of simplicity, standards, and developer experience—making Python feel as smooth as Node.js.

For an in-depth comparison of PDM, Pipenv, and Poetry, check out this article by PDM’s creator: A review: Pipenv vs Poetry vs PDM.


Further Reading: