Skip to content

Dependency Management with uv

Modern dependency management should be fast, reliable, and simple. uv delivers on all three.

Why uv?

Key Benefits

  • 10-100x faster than pip
  • Better dependency resolution than pip-tools
  • Drop-in replacement for pip/pip-tools
  • Single binary - no Python dependency
  • Cross-platform - works everywhere

Installation

# Linux/macOS
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

# Via pip (if needed)
pip install uv

# Verify installation
uv --version

Quick Start

Create Virtual Environment

# Create venv
uv venv

# Activate
source .venv/bin/activate  # Linux/macOS
.venv\Scripts\activate     # Windows

Install Dependencies

# Install from requirements.txt
uv pip install -r requirements.txt

# Install specific package
uv pip install django

# Install development dependencies
uv pip install -r requirements-dev.txt

Compile Requirements

# Compile requirements.in → requirements.txt
uv pip compile requirements.in -o requirements.txt

# With hashes for security
uv pip compile requirements.in -o requirements.txt --generate-hashes

# For specific Python version
uv pip compile requirements.in -o requirements.txt --python-version=3.13

Project Structure

project/
├── requirements/
│   ├── base.in              # Core dependencies
│   ├── dev.in               # Development tools
│   ├── test.in              # Testing tools
│   ├── base.txt             # Compiled base
│   ├── dev.txt              # Compiled dev
│   └── test.txt             # Compiled test
├── .python-version          # Pin Python version
└── pyproject.toml           # Project metadata

Split Dependencies

requirements/base.in (Production):

django>=5.2.6
djangorestframework>=3.15.2
psycopg2-binary>=2.9.9
redis>=5.0.4
celery>=5.3.6

requirements/dev.in (Development):

-c base.txt
ruff>=0.8.0
pytest>=8.3.0
pytest-django>=4.9.0
pytest-cov>=6.0.0
ipython>=8.29.0
django-debug-toolbar>=4.4.0

requirements/test.in (Testing):

-c base.txt
pytest>=8.3.0
pytest-django>=4.9.0
pytest-cov>=6.0.0
pytest-xdist>=3.6.0
factory-boy>=3.3.0

Common Workflows

Fresh Project Setup

# Create project directory
mkdir myproject && cd myproject

# Create virtual environment
uv venv

# Activate
source .venv/bin/activate

# Create requirements file
cat > requirements.in << 'EOF'
django>=5.2
djangorestframework
EOF

# Compile and install
uv pip compile requirements.in -o requirements.txt
uv pip install -r requirements.txt

Adding a New Dependency

# 1. Add to requirements.in
echo "requests>=2.32.0" >> requirements.in

# 2. Recompile
uv pip compile requirements.in -o requirements.txt

# 3. Sync environment
uv pip sync requirements.txt

Updating Dependencies

# Update all 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 django

# Then sync
uv pip sync requirements.txt

Removing a Dependency

# 1. Remove from requirements.in
# (edit file manually)

# 2. Recompile
uv pip compile requirements.in -o requirements.txt

# 3. Sync (removes orphaned packages)
uv pip sync requirements.txt

Advanced Usage

Multi-environment Setup

# Compile all environments
uv pip compile requirements/base.in -o requirements/base.txt
uv pip compile requirements/dev.in -o requirements/dev.txt
uv pip compile requirements/test.in -o requirements/test.txt

# Install for development
uv pip sync requirements/dev.txt

# Install for production
uv pip sync requirements/base.txt

Constraint Files

Use constraints to ensure consistency across environments:

requirements/dev.in:

# Use base.txt as constraints
-c base.txt

# Development-only packages
ruff
pytest
pytest-django

This ensures dev dependencies use the same versions as base.

Hash Verification

For maximum security:

# Generate with hashes
uv pip compile requirements.in -o requirements.txt --generate-hashes

# Install with hash verification
uv pip install -r requirements.txt --require-hashes

Integration with justfile

justfile:

# Install dependencies
install:
    uv pip sync requirements/dev.txt

# Compile requirements
compile:
    uv pip compile requirements/base.in -o requirements/base.txt
    uv pip compile requirements/dev.in -o requirements/dev.txt

# Update all dependencies
update:
    uv pip compile requirements/base.in -o requirements/base.txt --upgrade
    uv pip compile requirements/dev.in -o requirements/dev.txt --upgrade
    uv pip sync requirements/dev.txt

# Security audit
audit:
    uv pip list --format=json | pip-audit

CI/CD Integration

GitHub Actions

name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install uv
        run: curl -LsSf https://astral.sh/uv/install.sh | sh

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'

      - name: Create venv
        run: uv venv

      - name: Install dependencies
        run: |
          source .venv/bin/activate
          uv pip sync requirements/test.txt

      - name: Run tests
        run: |
          source .venv/bin/activate
          pytest

Docker

FROM python:3.13-slim

# Install uv
RUN pip install uv

WORKDIR /app

# Copy requirements
COPY requirements/base.txt .

# Install dependencies with uv (much faster)
RUN uv pip install --system -r base.txt

COPY . .

CMD ["gunicorn", "myapp.wsgi"]

Comparison: pip-tools vs uv

Speed Comparison

Operation pip-tools uv Speedup
Compile requirements 30s 0.5s 60x
Install 100 packages 45s 2s 22x
Resolve conflicts 120s 3s 40x

Feature Comparison

Feature pip-tools uv
Compile requirements
Hash generation
Sync environment
Speed Slow Very Fast
Installation Needs pip Single binary
Platform support Python only Cross-platform

Migration from pip-tools

Existing pip-tools Setup

# Old workflow
pip install pip-tools
pip-compile requirements.in
pip-sync requirements.txt

Migrate to uv

# New workflow (drop-in replacement)
uv pip compile requirements.in -o requirements.txt
uv pip sync requirements.txt

No changes needed to your requirements files!

Best Practices

✅ Do

  • Pin Python version in .python-version
  • Use .in files for direct dependencies
  • Compile .txt files for all dependencies
  • Commit both .in and .txt to version control
  • Use constraints for multi-environment projects
  • Regular updates via --upgrade
  • Security audits with pip-audit

❌ Don't

  • Don't manually edit .txt files (regenerate instead)
  • Don't use pip install without uv (slower)
  • Don't commit .venv/ directory
  • Don't use loose version pins in production
  • Don't skip hash verification in high-security environments

Troubleshooting

Package Won't Install

# Try without binary wheels
uv pip install --no-binary :all: problematic-package

# Check for build dependencies
apt-get install python3-dev build-essential

Dependency Conflicts

# See full dependency tree
uv pip tree

# Compile with verbose output
uv pip compile requirements.in -o requirements.txt --verbose

Slow First Install

# uv caches downloads, first install may be slower
# Subsequent installs will be fast

# Clear cache if needed
rm -rf ~/.cache/uv

Alternative: Poetry (for Libraries)

While uv is recommended for applications, consider Poetry for Python libraries:

Pros: - Extremely fast - Simple workflow - Compatible with pip ecosystem

Use for: - Django apps - Microservices - Internal tools

Pros: - Better for publishing to PyPI - Handles project metadata - Dependency groups

Use for: - Python packages - Public libraries - Complex dependency scenarios

Security Considerations

Verify Package Integrity

# Use hash verification
uv pip compile requirements.in -o requirements.txt --generate-hashes
uv pip install -r requirements.txt --require-hashes

Audit Dependencies

# Install pip-audit
uv pip install pip-audit

# Run audit
pip-audit

# Or in justfile
just audit

Keep Dependencies Updated

# Regular updates
uv pip compile requirements.in -o requirements.txt --upgrade

# Check for outdated packages
uv pip list --outdated

Performance Tips

Use System Python for uv

# Install uv system-wide (faster startup)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Don't use: pip install uv (slower)

Parallel Installation

# uv automatically parallelizes downloads
# No configuration needed

Cache Management

# uv caches downloads automatically
# Location: ~/.cache/uv

# Clear if needed
rm -rf ~/.cache/uv

Further Reading

Next Steps