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¶
Recommended Layout¶
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):
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:
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¶
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 installwithout 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¶
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)