This guide is the complete, canonical workflow for managing Python project dependencies using uv. It provides a clear, two-mode approach, production-ready best practices, and drop-in templates to ensure reproducibility, security, and developer efficiency across teams.
uv operates in two distinct modes. Your team should choose one and use it consistently.
- Project Mode (Recommended): This is the modern, preferred approach. It's managed by commands like
uv add,uv lock, anduv sync, using the cross-platformuv.lockfile as the single source of truth for reproducibility. - Requirements Mode (Compatibility): This mode mirrors the classic
pip-toolsworkflow and is useful when you need arequirements.txtfile for legacy tools or specific deployment platforms.
sequenceDiagram
participant Dev as Developer
participant Pyproject as pyproject.toml
participant UV as uv (CLI)
participant Venv as Virtual Environment
box Project Mode (Recommended & Canonical)
participant Lock as uv.lock
end
box Requirements Compatibility
participant Reqs as requirements.txt
end
alt Project/Lockfile Workflow (Recommended)
Dev->>UV: 1a. Run 'uv add "fastapi>=0.110"'
Note left of UV: Atomic: Edits pyproject.toml & updates uv.lock
UV->>Pyproject: Modify 'dependencies'
UV->>Lock: Update lock file
Dev->>UV: 1b. (Optional) Run 'uv lock --upgrade-package fastapi'
Note left of UV: Targeted upgrade
UV->>Pyproject: Read constraints
UV->>Lock: Update lock file with upgraded package
Dev->>UV: 2. Run 'uv sync'
Note left of UV: Reads uv.lock by default
UV->>Lock: Read pinned dependencies
UV->>Venv: Install/update/remove packages
else Requirements.txt Compatibility
Dev->>Pyproject: 1. Manually edit dependencies
Note right of Pyproject: Manual step required
alt Generate from pyproject.toml
Dev->>UV: 2a. Run 'uv pip compile pyproject.toml -o requirements.txt'
Note left of UV: Compiles from high-level intent
UV->>Pyproject: Read abstract dependencies
UV->>Reqs: Generate/overwrite requirements.txt
else Export from uv.lock (Preferred)
Dev->>UV: 2b. Run 'uv export --format requirements-txt > requirements.txt'
Note left of UV: Exports exact versions from lockfile truth
UV->>Lock: Read pinned dependencies
UV->>Reqs: Generate/overwrite requirements.txt
end
Dev->>UV: 3. Run 'uv pip sync requirements.txt'
UV->>Reqs: Read pinned dependencies
UV->>Venv: Install/update/remove packages
end
Use uv add and uv remove for all dependency changes. These commands are atomic, ensuring pyproject.toml and uv.lock remain perfectly in sync.
uv add "fastapi>=0.110"
uv add --group test pytest
uv remove fastapiUse the PEP 735 standard [dependency-groups] table in pyproject.toml to manage development and testing dependency sets.
# pyproject.toml
[project]
dependencies = ["fastapi>=0.110"]
requires-python = ">=3.11,<3.13"
[dependency-groups]
dev = ["ruff>=0.5"] # Synced by default
test = ["pytest>=8"]Enforce lock file consistency in your CI pipeline and locally.
- CI Check: Add this to your CI script to fail builds if the lock file is stale.
uv lock --check
- Pre-Commit Hook: Add a hook to
.pre-commit-config.yamlto run this check automatically.- repo: local hooks: - id: uv-lock-check name: Check uv.lock freshness entry: uv lock --check language: python types: [toml] files: ^pyproject\.toml$
If needed, export requirements.txt from the authoritative uv.lock file.
uv export --format requirements-txt > requirements.txtPolicy Note: In this repository, uv.lock is the single source of truth. A requirements.txt file is a temporary artifact.
- When should I use Project Mode (
uv.lock)?- Almost always. This is the default, modern, and most robust method. Use it for all new projects, especially those that need to work across different operating systems (macOS, Linux, Windows) or require strict reproducibility.
- When should I use Requirements Mode (
requirements.txt)?- For compatibility. Use this mode only when a legacy tool or deployment platform (e.g., some PaaS buildpacks, older CI systems) does not understand
pyproject.tomland explicitly requires arequirements.txtfile to function.
- For compatibility. Use this mode only when a legacy tool or deployment platform (e.g., some PaaS buildpacks, older CI systems) does not understand
- "My project was installed, but I didn't want it to be."
- Symptom: You see your own project in
pip list. - Fix: This is the default "editable install" behavior. For production-like environments or Docker builds, use
uv sync --no-editable.
- Symptom: You see your own project in
- "Dependencies resolved on my Mac but failed in Linux CI."
- Symptom:
uv syncfails with a resolution error in a different OS. - Fix: Ensure your
pyproject.tomlhas arequires-pythonentry that matches all target environments (e.g.,requires-python = ">=3.11,<3.13").
- Symptom:
- "Error:
uv.lockis not in sync withpyproject.toml."- Symptom: The
uv lock --checkcommand fails in CI. - Fix: A collaborator likely edited
pyproject.tomlmanually without runninguv lock. To fix, runuv locklocally, commit the updateduv.lockfile, and push again.
- Symptom: The
uv venv # Create virtual environment
uv add fastapi # Add a dependency
uv add --group dev ruff # Add a dev dependency
uv sync --group test # Sync venv with default, dev, and test groups
uv sync --no-dev # Sync venv with production dependencies only
uv lock --upgrade-package fastapi # Update a single package
uv lock --check # Verify lockfile is up-to-date (for CI/pre-commit)
uv run pytest # Run a command in the venv