PDM Cheat Sheet
Overview
PDM (Python Development Master) is a modern Python package and dependency manager that strictly follows PEP standards. It supports PEP 621 project metadata, PEP 517 build backends, and offers a lockfile mechanism similar to npm and Cargo for reproducible builds. PDM can work with virtual environments or PEP 582 local package directories.
PDM provides fast dependency resolution, a flexible plugin system, build and publish capabilities, and script management. It uses pyproject.toml as the single source of configuration and generates a pdm.lock file for deterministic installations.
Installation
# Via pipx (recommended)
pipx install pdm
# Via pip
pip install --user pdm
# macOS
brew install pdm
# Linux (installer script)
curl -sSL https://pdm-project.org/install-pdm.py | python3 -
# Verify
pdm --version
Core Commands
| Command | Description |
|---|---|
pdm init | Initialize a new project |
pdm add <pkg> | Add a dependency |
pdm remove <pkg> | Remove a dependency |
pdm install | Install all dependencies |
pdm update | Update dependencies |
pdm lock | Generate/update lockfile |
pdm run <cmd> | Run command in project environment |
pdm list | List installed packages |
pdm build | Build distribution packages |
pdm publish | Publish to PyPI |
pdm search <term> | Search for packages |
pdm self update | Update PDM itself |
Project Setup
# Initialize new project
pdm init
# Initialize with minimal prompts
pdm init --python 3.12 --backend pdm-backend
# Initialize in non-interactive mode
pdm init --non-interactive -n
pyproject.toml
[project]
name = "my-project"
version = "0.1.0"
description = "My Python project"
requires-python = ">=3.10"
readme = "README.md"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "you@example.com"},
]
dependencies = [
"requests>=2.28",
"click>=8.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"ruff>=0.3",
]
[project.scripts]
mycli = "my_project.cli:main"
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[tool.pdm]
distribution = true
[tool.pdm.dev-dependencies]
test = [
"pytest>=7.0",
"pytest-cov",
]
lint = [
"ruff",
"mypy",
]
Dependency Management
# Add production dependency
pdm add requests flask sqlalchemy
# Add with version constraint
pdm add "requests>=2.28,<3.0"
pdm add "django~=4.2"
# Add dev dependency
pdm add -dG test pytest pytest-cov
pdm add -dG lint ruff mypy
# Add optional dependency group
pdm add -G docs mkdocs mkdocs-material
# Remove dependency
pdm remove requests
# Update all dependencies
pdm update
# Update specific package
pdm update requests
# Update dev dependencies only
pdm update -dG test
# Install from lockfile (exact versions)
pdm install
# Install with specific groups
pdm install -G docs
pdm install -dG test,lint
# Show dependency tree
pdm list --tree
# Show outdated packages
pdm update --dry-run
Scripts and Tasks
# pyproject.toml
[tool.pdm.scripts]
start = "python -m my_project"
test = "pytest tests/ -v"
lint = "ruff check src/"
format = "ruff format src/ tests/"
typecheck = "mypy src/"
# Composite script
check = {composite = ["lint", "typecheck", "test"]}
# Script with environment variables
dev = {cmd = "uvicorn my_project.app:app --reload", env = {DEBUG = "1"}}
# Shell script
migrate = {shell = "python manage.py migrate && echo 'Done'"}
# Pre/post hooks
pre_test = "echo 'Setting up tests...'"
post_test = "echo 'Tests complete!'"
pdm run start
pdm run test
pdm run check
pdm run dev
Configuration
PDM Config
# Show config
pdm config
# Set Python interpreter
pdm use 3.12
pdm use /usr/bin/python3.12
# Configure venv backend
pdm config venv.backend virtualenv
pdm config venv.in_project true
# Configure PyPI index
pdm config pypi.url https://pypi.org/simple/
# Private index
pdm config pypi.extra.url https://private.pypi.org/simple/
pdm config pypi.extra.username myuser
pdm config pypi.extra.password mypass
Virtual Environment
# Create venv (automatic with pdm install)
pdm venv create 3.12
# List venvs
pdm venv list
# Activate venv
eval $(pdm venv activate)
# Remove venv
pdm venv remove my-project-3.12
# Use in-project .venv
pdm config venv.in_project true
Lock Strategies
# Generate lockfile
pdm lock
# Cross-platform lock
pdm lock --strategy cross_platform
# Lock without hashes
pdm lock --no-hashes
# Export to requirements.txt
pdm export -f requirements -o requirements.txt
# Export with dev deps
pdm export -f requirements --dev -o requirements-dev.txt
Advanced Usage
Build and Publish
# Build sdist and wheel
pdm build
# Publish to PyPI
pdm publish
# Publish to Test PyPI
pdm publish --repository testpypi
# Publish with credentials
pdm publish --username __token__ --password pypi-xxx
Plugins
# Install PDM plugin
pdm self add pdm-bump
pdm self add pdm-autoexport
# List installed plugins
pdm self list
# Remove plugin
pdm self remove pdm-bump
Monorepo Support
# Root pyproject.toml
[tool.pdm.dev-dependencies]
dev = ["-e file:///${PROJECT_ROOT}/packages/shared"]
# Or path dependency
[project]
dependencies = [
"shared @ file:///${PROJECT_ROOT}/packages/shared",
]
CI/CD Integration
# GitHub Actions
- uses: pdm-project/setup-pdm@v4
with:
python-version: '3.12'
cache: true
- run: pdm install
- run: pdm run test
Troubleshooting
| Issue | Solution |
|---|---|
| Resolution conflict | Run pdm update --unconstrained to find issues |
| Lock file outdated | Run pdm lock --update-reuse |
| Wrong Python version | Run pdm use <version> to select interpreter |
| Package not found | Check index configuration with pdm config pypi.url |
| Import error after install | Ensure pdm install completed; check pdm list |
| Slow resolution | Use pdm lock --strategy no_cross_platform |
# Verbose output
pdm install -v
# Check project health
pdm check
# Show dependency tree
pdm list --tree --reverse
# Clear cache
pdm cache clear
# Debug resolution
pdm lock -v