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.txtonly 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:
pipandrequirements.txtdon’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, andpdm updateare intuitive and similar to npm.
PDM vs. Poetry and uv: Why We Chose PDM
| Feature | PDM | Poetry | uv |
|---|---|---|---|
| Standards-based | Yes (pyproject.toml) | Yes (pyproject.toml) | Yes (pyproject.toml) |
| Virtual env mgmt | Automatic | Automatic | Automatic |
| Lock file | Yes (pdm.lock) | Yes (poetry.lock) | Yes (uv.lock) |
| Editable installs | Yes | Yes | Yes |
| CLI experience | npm-like, simple | Rich, but opinionated | Fast, minimal |
| Speed | Fast | Moderate | Very fast |
| Ecosystem adoption | Growing | Widely adopted | Growing Very Fast |
Getting Started: Setting Up PDM
Step 1: Install pipx (Recommended)
PDM works best when installed via pipx to avoid global package conflicts.
python3 -m pip install --user pipxpython3 -m pipx ensurepathStep 2: Install PDM
pipx install pdmStep 3: Initialize Your Project
mkdir pdm-ref-projectcd pdm-ref-projectpdm init- Answer the prompts to set up your project metadata and dependencies.
Step 4: Add Dependencies
pdm add requestsStep 5: Run Your Code
pdm run python main.pyReal-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: