Advanced patterns for managing Python dependencies with uv.
For any project with a pyproject.toml, uv manages a uv.lock automatically.
This is the reproducible, uv-native workflow — prefer it over a hand-managed
requirements.txt.
uv add "flask>=2.0" sqlalchemy # add runtime deps; uv.lock updated
uv add --dev pytest ruff mypy # dev-only dependency group
uv remove flask # drop a dep
uv sync # install exactly from uv.lock
uv sync --frozen # CI: fail if uv.lock is stale, don't re-resolve
uv lock --upgrade # bump everything within constraints
uv lock --upgrade-package flask # bump just one
Use this only when you specifically need a requirements.txt — Docker layer
caching, non-uv CI, or legacy tooling. Otherwise prefer uv.lock above.
# requirements.in (loose constraints)
flask>=2.0
sqlalchemy>=2.0
pydantic>=2.0
# Generate locked requirements.txt
uv pip compile requirements.in -o requirements.txt
# Install exact versions
uv pip sync requirements.txt
# requirements.in
flask>=2.0
sqlalchemy>=2.0
# requirements-dev.in
-r requirements.in
pytest>=7.0
ruff>=0.1
mypy>=1.0
# Compile both
uv pip compile requirements.in -o requirements.txt
uv pip compile requirements-dev.in -o requirements-dev.txt
# Install for development
uv pip sync requirements-dev.txt
# Update all packages to latest compatible versions
uv pip compile requirements.in -o requirements.txt --upgrade
# Update specific package
uv pip compile requirements.in -o requirements.txt --upgrade-package flask
# Update with constraints
uv pip compile requirements.in -o requirements.txt --upgrade --constraint constraints.txt
# constraints.txt
# Pin versions that need to be consistent across projects
numpy==1.26.0
pandas==2.0.0
# Use constraints during compile
uv pip compile requirements.in -o requirements.txt --constraint constraints.txt
# Python 3.10
uv pip compile requirements.in -o requirements-py310.txt --python-version 3.10
# Python 3.11
uv pip compile requirements.in -o requirements-py311.txt --python-version 3.11
# Linux
uv pip compile requirements.in -o requirements-linux.txt --platform linux
# macOS
uv pip compile requirements.in -o requirements-macos.txt --platform macos
# Windows
uv pip compile requirements.in -o requirements-windows.txt --platform windows
my-monorepo/
├── pyproject.toml # Root workspace config
├── packages/
│ ├── core/
│ │ └── pyproject.toml
│ ├── api/
│ │ └── pyproject.toml
│ └── cli/
│ └── pyproject.toml
[tool.uv.workspace]
members = ["packages/*"]
[tool.uv.sources]
my-core = { workspace = true }
my-api = { workspace = true }
# packages/core/pyproject.toml
[project]
name = "my-core"
version = "0.1.0"
dependencies = ["pydantic>=2.0"]
# packages/api/pyproject.toml
[project]
name = "my-api"
version = "0.1.0"
dependencies = ["my-core", "fastapi>=0.100"]
# Install all workspace members into one env (native — no editable pip installs)
uv sync
# Run a command in the workspace env
uv run pytest
# Operate on a specific member
uv run --package my-api pytest
[[tool.uv.index]]
name = "private"
url = "https://pypi.private.com/simple/"
uv add my-private-package # resolves against configured indexes
# Per-index credentials: UV_INDEX_<NAME>_USERNAME / _PASSWORD
export UV_INDEX_PRIVATE_USERNAME=user
export UV_INDEX_PRIVATE_PASSWORD=token
uv add my-private-package
--extra-index-url https://pypi.private.com/simple/
my-public-package>=1.0
my-private-package>=2.0
# In pyproject.toml
[project]
dependencies = [
"my-package @ git+https://github.com/user/repo.git",
"my-package @ git+https://github.com/user/repo.git@v1.0.0",
"my-package @ git+https://github.com/user/repo.git@main",
"my-package @ git+ssh://git@github.com/user/repo.git",
]
# requirements.in
git+https://github.com/user/repo.git@main#egg=my-package
# In pyproject.toml
[project]
dependencies = [
"my-local @ file:///path/to/package",
]
# Relative path
[tool.uv.sources]
my-local = { path = "../my-local-package" }
# Use backtracking resolver (more thorough but slower)
uv pip compile requirements.in -o requirements.txt --resolver=backtracking
# Allow prereleases
uv pip compile requirements.in -o requirements.txt --prerelease=allow
# Exclude specific packages from upgrade
uv pip compile requirements.in -o requirements.txt --upgrade --no-upgrade-package numpy
# Show why a version was chosen
uv pip compile requirements.in --verbose
# Generate dependency tree
uv pip tree
# Check for conflicts
uv pip check
# Clear uv cache
uv cache clean
# Show cache location
uv cache dir
# Disable cache for one command
uv pip install --no-cache package-name
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Install dependencies
run: uv sync --frozen
- name: Run tests
run: uv run pytest
- name: Cache uv
uses: actions/cache@v3
with:
path: ~/.cache/uv
key: uv-${{ hashFiles('uv.lock') }}
restore-keys: uv-
- name: Verify lock file is up to date
run: uv lock --check
uv pip check - Catch conflicts early--upgrade