

The Complete Beginner's Guide to uv: Python's Lightning-Fast Package Manager
Install free and open source application on Linux, Docker, Virtualization, Ansible Automation
uv is a modern, high-performance Python package manager written in Rust that serves as a drop-in replacement for traditional tools like pip, pip-tools, virtualenv, poetry, and more. With speeds up to 100x faster than pip and a unified approach to Python project management, uv represents the next generation of Python tooling.
🧠 Why uv Matters: Unlike traditional Python package managers that evolved separately over time, uv was designed from the ground up as a unified solution. It combines package installation, dependency resolution, virtual environment management, Python version handling, and project scaffolding into a single, lightning-fast tool. This means fewer commands to remember, faster installations, and a more consistent development experience.
What Makes uv Special#
uv offers several compelling advantages over existing tools:
- Extreme Speed: 10-100x faster than pip, with installations completing in seconds rather than minutes
- All-in-One Solution: Replaces pip, pip-tools, virtualenv, poetry, pyenv, and more
- Drop-in Compatibility: Works with existing pip workflows and requirements.txt files
- Modern Architecture: Built in Rust for optimal performance and reliability
- Automatic Environment Management: Handles virtual environments seamlessly behind the scenes
Installation#
Getting started with uv is straightforward, with multiple installation options to suit different preferences:
Quick Installation#
For Unix/Linux/macOS:
curl -LsSf https://astral.sh/uv/install.sh | shbashFor Windows:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"powershellAlternative Installation Methods#
Via Homebrew (macOS):
brew install uvbashVia pip (if you have Python already):
pip install uvbashVerify Installation:
uv --version
# Output: uv 0.7.9 (or latest version)bashCore Project Management#
Creating a New Python Project from Scratch#
🧠 Project Creation Philosophy: uv takes an opinionated approach to project structure, automatically setting up best practices that many developers configure manually. This includes proper directory structure, configuration files, and even Git initialization.
Basic Project Creation#
# Create a simple application project
uv init my-awesome-app
cd my-awesome-app
# View the created structure
ls -la
# Output:
# .python-version
# README.md
# main.py
# pyproject.tomlbashProject Type Options#
# For installable packages
uv init my-package --package
# For libraries (with src/ layout)
uv init my-library --lib
# For applications (with app/ layout)
uv init my-web-app --app
# Minimal setup without sample files
uv init my-project --barebashExpected Output:
Initialized project `my-awesome-app` at `/path/to/my-awesome-app`bashInitializing uv in an Existing Python Project#
If you have an existing Python project, you can easily add uv support:
# Navigate to your existing project
cd /path/to/existing-project
# Initialize uv (won't overwrite existing files)
uv init --bare
# Import existing requirements
uv add -r requirements.txt
uv add -r requirements-dev.txt --devbash🧠 Compatibility Note: uv is designed to work alongside existing Python projects. The --bare flag ensures that uv won’t overwrite your existing main.py or README.md files, making migration safe and non-destructive.
Project Structure and Configuration Files#
Key Files Explained#
pyproject.toml - The central configuration file:
[project]
name = "my-awesome-app"
version = "0.1.0"
description = "My awesome Python application"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"requests>=2.28.0",
"fastapi>=0.95.0",
]
[tool.uv]
dev-dependencies = [
"pytest>=7.4.0",
"black>=23.7.0",
"ruff>=0.0.280",
]toml.python-version - Specifies the Python version for the project:
3.11bashuv.lock - Automatically generated lockfile containing exact dependency versions (similar to package-lock.json in Node.js):
version = 1
[[package]]
name = "requests"
version = "2.30.0"
dependencies = ["certifi>=2017.4.17", "charset-normalizer>=2.0.0"]toml🧠 Lockfile Benefits: The uv.lock file ensures that everyone on your team gets exactly the same versions of dependencies, preventing the “it works on my machine” problem. Unlike pip’s requirements.txt, uv.lock includes transitive dependencies and cross-platform compatibility information.
Package Management#
Adding, Removing, and Updating Packages#
Adding Dependencies#
# Add a basic package
uv add requests
# Output: Resolved 4 packages in 234ms
# Installed 4 packages in 12ms
# + certifi==2024.7.4
# + charset-normalizer==3.3.2
# + idna==3.7
# + requests==2.32.3
# Add package with version constraint
uv add "django>=4.2.0,<5.0.0"
# Add package with extras
uv add "fastapi[all]"
# Add multiple packages at once
uv add requests flask sqlalchemybashRemoving Dependencies#
# Remove a package
uv remove requests
# Output: Removed 4 packages in 5ms
# - certifi==2024.7.4
# - charset-normalizer==3.3.2
# - idna==3.7
# - requests==2.32.3
# Remove multiple packages
uv remove flask sqlalchemybashUpdating Dependencies#
# Update all dependencies
uv lock --upgrade
# Update specific package
uv lock --upgrade-package requests
# Update to latest compatible versions
uv add requests --upgradebashDevelopment vs Production Dependencies#
uv provides clear separation between production and development dependencies:
# Add production dependencies
uv add fastapi uvicorn
# Add development dependencies
uv add --dev pytest black ruff mypy
# Add to specific dependency groups
uv add --group test pytest pytest-cov
uv add --group lint black ruffbashpyproject.toml structure:
[project]
dependencies = [
"fastapi>=0.100.0",
"uvicorn>=0.20.0",
]
[tool.uv.dev-dependencies]
test = [
"pytest>=7.4.0",
"pytest-cov>=4.1.0",
]
lint = [
"black>=23.7.0",
"ruff>=0.0.280",
]tomlVersion Constraints and Lock Files#
Version Constraint Examples#
# Exact version
uv add "django==4.2.7"
# Minimum version
uv add "requests>=2.28.0"
# Version range
uv add "flask>=2.0.0,<3.0.0"
# Compatible release
uv add "numpy~=1.24.0" # Equivalent to >=1.24.0,<1.25.0
# Pre-release versions
uv add --prerelease=allow "django>=5.0.0"bashWorking with Lock Files#
# Generate/update lock file
uv lock
# Install from lock file
uv sync
# Install only production dependencies
uv sync --no-dev
# Install with specific groups
uv sync --group test --group lintbash🧠 Lock File Strategy: Always commit uv.lock to version control. This ensures that your CI/CD pipeline, production deployments, and teammate environments use exactly the same dependency versions, eliminating dependency-related bugs.
Installing from Different Sources#
PyPI (Default)#
uv add requests # Latest version from PyPIbashGit Repositories#
# From GitHub
uv add git+https://github.com/django/django.git
# Specific branch
uv add git+https://github.com/django/django.git@main
# Specific tag
uv add git+https://github.com/django/django.git@4.2.7
# Specific commit
uv add git+https://github.com/django/django.git@abc123def456bashLocal Paths#
# Local package in development
uv add ./my-local-package
# Editable install (changes reflected immediately)
uv add -e ./my-local-package
# From local wheel file
uv add ./dist/my-package-1.0.0-py3-none-any.whlbashPrivate Package Indexes#
# Custom index
uv add --index https://my-private-pypi.com/simple/ my-private-package
# With authentication
UV_INDEX_USERNAME=myuser UV_INDEX_PASSWORD=mypass uv add my-private-packagebashVirtual Environment Operations#
How uv Automatically Manages Virtual Environments#
🧠 Automatic Environment Management: One of uv’s biggest advantages is that it eliminates the manual virtual environment dance that Python developers have performed for years. No more remembering to activate environments or worrying about installing packages in the wrong place.
Comparison: Traditional vs uv Approach#
Traditional pip + virtualenv workflow:
# Manual process - easy to forget steps
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python main.py
deactivatebashuv workflow:
# Automatic - uv handles everything
uv run main.py # Creates environment, installs dependencies, runs scriptbashBehind the Scenes#
When you run uv run or uv sync, uv automatically:
- Checks if a virtual environment exists (
.venvdirectory) - Creates one if it doesn’t exist, using the Python version from
.python-version - Ensures all dependencies from
pyproject.tomlare installed - Runs your command in the proper environment
Environment Activation and Deactivation#
While uv manages environments automatically, you can still manually activate them when needed [^30]:
# uv creates environments in .venv by default
source .venv/bin/activate # Unix/Linux/macOS
# or
.venv\Scripts\activate # Windows
# Verify active environment
which python
# Output: /path/to/project/.venv/bin/python
# Deactivate
deactivatebashHowever, the recommended approach is to use uv run:
# Instead of activating, just use uv run
uv run python main.py
uv run pytest
uv run black .bashListing and Switching Between Project Environments#
Viewing Environment Information#
# Show installed packages
uv pip list
# Output: Package Version
# ------------ -------
# requests 2.32.3
# certifi 2024.7.4
# Show dependency tree
uv pip tree
# Output: requests==2.32.3
# ├── certifi [required: >=2017.4.17]
# ├── charset-normalizer [required: >=2.0.0]
# └── idna [required: >=2.5]
# Show package details
uv pip show requestsbashManaging Multiple Python Versions#
# List available Python versions
uv python list
# Install specific Python version
uv python install 3.11
uv python install 3.12
# Pin Python version for project
uv python pin 3.11
# Create environment with specific Python version
uv venv --python 3.12bashRecreating or Resetting Virtual Environments#
Complete Environment Reset#
# Remove environment and lock file
rm -rf .venv uv.lock
# Recreate from scratch
uv sync
# Output: Using CPython 3.11.7
# Creating virtual environment at: .venv
# Resolved 15 packages in 145ms
# Installed 15 packages in 23msbashPartial Reset Options#
# Clear cache and reinstall
uv cache clean
uv sync --reinstall
# Reset lock file only
rm uv.lock
uv lock
# Sync with latest dependencies
uv sync --upgradebash🧠 When to Reset: Environment resets are useful when you suspect dependency corruption, want to test with latest versions, or need to change Python versions. The process is much faster with uv than traditional tools due to its caching system.
Project Cleanup and Maintenance#
Completely Removing a Project and Virtual Environment#
Full Project Cleanup#
# Navigate out of project directory
cd ..
# Remove entire project (including .venv)
rm -rf my-project/
# Or keep source code, remove only uv files
cd my-project
rm -rf .venv uv.lockbashSelective Cleanup#
# Remove only virtual environment
rm -rf .venv
# Remove lock file (will be regenerated)
rm uv.lock
# Remove build artifacts
rm -rf dist/ build/ *.egg-info/bashCleaning Cache and Temporary Files#
Cache Management#
# Show cache directory location
uv cache dir
# Output: /home/user/.cache/uv
# Check cache size
uv cache clean --dry-run
# Output: Would remove 1.2 GB from cache
# Clean entire cache
uv cache clean
# Output: Removed 1.2 GB from cache
# Clean specific package from cache
uv cache clean --package requestsbashDisk Space Optimization#
# View cache statistics by package
du -sh ~/.cache/uv/*
# Output: 145M archives
# 89M builds
# 67M wheels
# Clean old/unused cached items
uv cache clean --older-than 30dbashResetting Dependencies and Starting Fresh#
Dependency Reset Strategies#
# Strategy 1: Reset lock file, keep pyproject.toml
rm uv.lock
uv lock
# Strategy 2: Reset everything, reimport from requirements.txt
rm uv.lock pyproject.toml
uv init --bare
uv add -r requirements.txt
# Strategy 3: Update all dependencies to latest
uv lock --upgrade
uv syncbashTroubleshooting Dependency Issues#
# Check for dependency conflicts
uv pip check
# Output: No broken requirements found.
# Verbose dependency resolution
uv lock --verbose
# Force reinstall all packages
uv sync --reinstallbashBest Practices for Project Organization#
Project Structure Recommendations [^25]:#
- Use consistent Python versions: Pin specific versions in
.python-version - Organize dependencies logically: Separate dev, test, and production dependencies
- Version control important files: Always commit
pyproject.tomlanduv.lock - Ignore generated files: Add
.venv/to.gitignore - Document dependencies: Maintain clear descriptions in
pyproject.toml
Example .gitignore for uv projects:#
# Virtual environment
.venv/
# Build artifacts
dist/
build/
*.egg-info/
# Cache directories
__pycache__/
*.pyc
*.pyo
# IDE files
.vscode/
.idea/
# OS files
.DS_Store
Thumbs.dbplaintextFramework-Specific Usage#
FastAPI Projects#
Quick FastAPI Setup#
# Create FastAPI project
uv init my-fastapi-app --app
cd my-fastapi-app
# Add FastAPI with all extras
uv add "fastapi[standard]"
# Add common FastAPI dependencies
uv add "sqlalchemy>=2.0.0" "alembic>=1.11.0" "python-jose[cryptography]"
# Add development dependencies
uv add --dev pytest pytest-asyncio httpx black ruff mypy
# Run development server
uv run fastapi dev
# Output: INFO: Uvicorn running on http://127.0.0.1:8000bashFastAPI Project Structure#
my-fastapi-app/
├── .venv/ # Virtual environment
├── .python-version # Python version
├── pyproject.toml # Dependencies and config
├── uv.lock # Lock file
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app
│ ├── models.py # SQLAlchemy models
│ ├── schemas.py # Pydantic schemas
│ └── routers/
│ ├── auth.py
│ └── users.py
├── tests/
│ ├── conftest.py
│ └── test_main.py
└── alembic/ # Database migrationsbashFastAPI Development Commands#
# Development server with auto-reload
uv run fastapi dev --host 0.0.0.0 --port 8080
# Production server
uv run fastapi run
# Testing
uv run pytest --cov=app
# Code quality
uv run black .
uv run ruff check .
uv run mypy app/
# Database migrations
uv run alembic revision --autogenerate -m "Create tables"
uv run alembic upgrade headbashDjango Projects#
Django Project Setup#
# Create project directory
mkdir my-django-project
cd my-django-project
# Initialize uv project
uv init --bare
# Add Django and common dependencies
uv add "django>=4.2.0" "django-cors-headers>=4.0.0" "djangorestframework>=3.14.0"
uv add "psycopg2-binary>=2.9.0" # PostgreSQL driver
# Add development dependencies
uv add --dev "django-debug-toolbar>=4.1.0" pytest pytest-django black ruff
# Create Django project structure
uv run django-admin startproject config .
uv run python manage.py startapp accounts
uv run python manage.py startapp corebashDjango Development Commands#
# Run development server
uv run python manage.py runserver
# Database operations
uv run python manage.py makemigrations
uv run python manage.py migrate
uv run python manage.py createsuperuser
# Django shell
uv run python manage.py shell
# Run tests
uv run pytest
uv run python manage.py test
# Collect static files
uv run python manage.py collectstaticbashDjango Settings Configuration#
config/settings/base.py:
import environ
env = environ.Env(DEBUG=(bool, False))
environ.Env.read_env()
# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': env('DB_NAME'),
'USER': env('DB_USER'),
'PASSWORD': env('DB_PASSWORD'),
'HOST': env('DB_HOST', default='localhost'),
'PORT': env('DB_PORT', default='5432'),
}
}pythonFramework-Specific Dependencies and Workflows#
Common Web Development Stack#
# FastAPI + PostgreSQL + Redis
uv add "fastapi[standard]" "sqlalchemy[postgresql]" "redis>=4.5.0"
# Django + PostgreSQL + Celery
uv add "django>=4.2.0" "psycopg2-binary" "celery[redis]" "django-cors-headers"
# Data Science Stack
uv add "pandas>=2.0.0" "numpy>=1.24.0" "matplotlib>=3.7.0" "jupyter>=1.0.0"
# Testing Stack
uv add --dev "pytest>=7.4.0" "pytest-cov>=4.1.0" "pytest-mock>=3.11.0"bashEnvironment-Specific Configuration#
# pyproject.toml
[project.optional-dependencies]
dev = [
"django-debug-toolbar>=4.1.0",
"django-extensions>=3.2.0",
]
prod = [
"gunicorn>=21.0.0",
"whitenoise>=6.5.0",
]
test = [
"pytest-django>=4.5.0",
"factory-boy>=3.3.0",
]toml# Install different configurations
uv sync --extra dev # Development
uv sync --extra prod --no-dev # Production
uv sync --extra test # TestingbashAdvanced Tips and Comparisons#
Performance Benefits with Concrete Examples#
Real-World Performance Comparison#
Installing a typical Flask web application:
- pip: 7.5 seconds (cold cache)
- uv: 1.5 seconds (cold cache)
- uv with warm cache: 0.15 seconds
Large Django project with 100+ dependencies:
- pip: 58 seconds (cold cache)
- uv: 5.8 seconds (cold cache)
- uv with warm cache: 0.5 seconds
Performance Factors Behind uv’s Speed#
🧠 Why uv is So Fast: uv’s performance comes from several technical innovations:
- Rust Implementation: Compiled code runs much faster than interpreted Python
- Parallel Downloads: Downloads multiple packages simultaneously
- Efficient Caching: Global cache with hardlinks reduces disk I/O
- Optimized Resolver: Advanced dependency resolution algorithm
- Copy-on-Write: Leverages modern filesystem features
Workflow Improvements and Time-Saving Features#
Smart Caching System#
# First project setup
cd project1
uv add requests flask
# Downloads and caches packages
# Second project reuses cache
cd ../project2
uv add requests # Instant - uses cached versionbashAutomatic Environment Management#
# Traditional workflow
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python main.py
deactivate
# uv workflow
uv run main.py # Everything happens automaticallybashDevelopment Tool Integration#
# Run development tools without installation
uvx black . # Format code
uvx ruff check . # Lint code
uvx mypy src/ # Type checking
uvx pytest # Run tests
# Install tools permanently for the project
uv tool install black
uv tool install ruffbashIntegration with IDEs and Development Tools#
VS Code Integration#
.vscode/settings.json:
{
"python.defaultInterpreterPath": "./.venv/bin/python",
"python.terminal.activateEnvironment": false,
"python.testing.pytestEnabled": true,
"python.testing.pytestArgs": ["tests/"],
"python.formatting.provider": "black",
"python.linting.enabled": true,
"python.linting.ruffEnabled": true
}jsonPyCharm Integration#
- Set Project Interpreter: File → Settings → Project → Python Interpreter
- Select Existing Environment: Choose
.venv/bin/python - Configure Test Runner: Use pytest with automatic discovery
CI/CD Integration#
GitHub Actions Example:
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v1
- name: Set up Python
run: uv python install
- name: Install dependencies
run: uv sync
- name: Run tests
run: uv run pytestyamlCommon Troubleshooting Scenarios and Solutions#
Installation Issues#
Problem: Permission denied during installation
# Solution: Fix ownership or use alternative installation
sudo chown -R $USER ~/.local/share/uv
# or
pip install uv # Alternative installation methodbashProblem: Package not found
# Solution: Check package name and availability
uv add --dry-run package-name # Test without installing
# or search PyPI directlybashEnvironment Issues#
Problem: Wrong Python version used
# Solution: Pin specific Python version
uv python pin 3.11
uv sync # Recreate environment with correct versionbashProblem: Dependency conflicts
# Solution: Use verbose output to diagnose
uv lock --verbose
# Check for incompatible version constraints
uv pip checkbashPerformance Issues#
Problem: Slow installation despite uv’s reputation
# Solution: Check cache and network
uv cache clean # Clear corrupted cache
UV_VERBOSITY=debug uv add package-name # Debug outputbashMigration Guide from pip/pipenv/poetry to uv#
From pip + virtualenv#
Current workflow:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtbashNew uv workflow:
uv init --bare
uv add -r requirements.txt
uv run main.pybashFrom Poetry#
Automated migration:
uvx migrate-to-uv # Automatic conversion toolbashManual migration:
uv init --bare
# Copy dependencies from poetry's pyproject.toml
uv add requests "fastapi>=0.100.0" "uvicorn>=0.20.0"
uv add --dev pytest black ruffbashCommand Translation Reference#
Conclusion#
uv represents a significant leap forward in Python package management, offering dramatic performance improvements while maintaining compatibility with existing workflows. Its unified approach eliminates the complexity of managing multiple tools, while its Rust-based architecture delivers the speed and reliability that modern development demands.
🧠 The Future of Python Development: uv’s approach of combining multiple tools into a single, fast, reliable binary represents where Python tooling is heading. By eliminating the friction of environment management and dependency resolution, developers can focus on what matters most: writing great Python code.
Key takeaways for getting started:
- Start simple: Use
uv initfor new projects anduv runfor execution - Leverage speed: Take advantage of uv’s caching for faster CI/CD pipelines
- Maintain compatibility: Use uv’s pip interface for gradual migration
- Embrace automation: Let uv handle virtual environments and dependency management
- Stay organized: Use clear dependency groups and proper project structure
Whether you’re building web applications with FastAPI or Django, managing data science projects, or developing Python packages, uv provides the speed, reliability, and simplicity that modern Python development requires. The transition from traditional tools is straightforward, and the performance benefits are immediately apparent.
As the Python ecosystem continues to evolve, tools like uv demonstrate how modern technologies can enhance the development experience while maintaining the simplicity and accessibility that Python developers value. By adopting uv, you’re not just getting a faster package manager—you’re embracing a more efficient, more reliable approach to Python development.