uv: The Fast Python Package Manager Replacing pip in 2026
Introduction
Python package management has long been a point of frustration for developers. Between pip, virtualenv, pip-tools, pyenv, and poetry, the ecosystem became fragmented and slow. In 2024, Astral — the team behind the popular ruff linter — released uv, a blazing-fast Python package manager written in Rust that aims to replace them all.
By 2026, uv has become the de-facto standard for Python dependency management in new projects. It's 10–100x faster than pip, handles virtual environments automatically, and provides a unified toolchain from Python version management to dependency locking.
In this guide, you'll learn everything you need to start using uv in your Python projects, including FastAPI and Django applications.
🔗 Related: Building RESTful APIs with FastAPI: Best Practices and Patterns
Why Python Package Management Has Always Been Painful
For years, the typical Python project setup required multiple tools:
pyenvto manage Python versionsvirtualenvorvenvto create isolated environmentspipto install packagespip-toolsorpoetryto lock dependenciespip-compileto generate reproduciblerequirements.txtfiles
Each tool had its own configuration, its own quirks, and its own performance bottlenecks. pip is written in Python itself, which means it has to bootstrap Python before it can do anything. On large projects, pip install could take minutes.
Poetry improved the experience significantly, but it introduced its own complexity and was still noticeably slow.
uv solves all of this with a single, Rust-powered binary that handles the entire workflow.
What is uv?
uv is a Python package manager and project manager built by Astral. Under the hood, it's written in Rust and uses a dependency resolver based on PubGrub — the same algorithm used by Dart's package manager.
Key capabilities:
- Install Python packages (drop-in replacement for
pip) - Create and manage virtual environments (replacement for
virtualenv) - Lock dependencies (replacement for
pip-tools) - Manage Python versions (replacement for
pyenv) - Run scripts with inline dependencies (replacement for
pipx/manual venvs) - Manage monorepo workspaces
Performance benchmarks from Astral's own testing show uv is:
- ~8x faster than pip for cold installs
- ~80x faster than pip with a warm cache
This is transformative for CI/CD pipelines where install time directly affects build minutes and costs.
Installing uv
uv provides a standalone installer that doesn't require Python to be installed first.
macOS and Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Via pip (if you already have Python)
pip install uv
Verify Installation
uv --version
# uv 0.5.x (or similar)
Shell Completion
# bash
echo 'eval "$(uv generate-shell-completion bash)"' >> ~/.bashrc
# zsh
echo 'eval "$(uv generate-shell-completion zsh)"' >> ~/.zshrc
uv Basics: Virtual Environments and Installing Packages
Creating a Virtual Environment
# Create a .venv in the current directory
uv venv
# Create with a specific Python version
uv venv --python 3.12
# Create at a custom path
uv venv ./my-env
Activating the Environment
# macOS/Linux
source .venv/bin/activate
# Windows
.venv\Scripts\activate
Installing Packages
# Install a package
uv pip install fastapi
# Install multiple packages
uv pip install fastapi uvicorn sqlalchemy
# Install from requirements.txt
uv pip install -r requirements.txt
# Install with extras
uv pip install "fastapi[all]"
# Install a specific version
uv pip install "fastapi==0.115.0"
The uv pip Command
All pip subcommands work through uv pip:
uv pip install <package>
uv pip uninstall <package>
uv pip list
uv pip show fastapi
uv pip freeze > requirements.txt
uv pip compile requirements.in -o requirements.txt
Managing Projects with uv init and pyproject.toml
Modern Python projects use pyproject.toml as a single source of truth for project metadata, dependencies, and tooling configuration. uv embraces this standard fully.
Initializing a New Project
# Create a new project
uv init my-api
cd my-api
This generates:
my-api/
├── .python-version # Pinned Python version
├── .venv/ # Virtual environment (auto-created)
├── pyproject.toml # Project config and dependencies
├── README.md
└── src/
└── my_api/
└── __init__.py
The pyproject.toml File
[project]
name = "my-api"
version = "0.1.0"
description = "My FastAPI project"
requires-python = ">=3.12"
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Adding Dependencies
# Add a runtime dependency
uv add fastapi uvicorn
# Add a development dependency
uv add --dev pytest ruff mypy
# Add with version constraints
uv add "sqlalchemy>=2.0"
# Remove a dependency
uv remove requests
After running uv add, the pyproject.toml is automatically updated:
[project]
dependencies = [
"fastapi>=0.115.0",
"uvicorn>=0.32.0",
"sqlalchemy>=2.0.0",
]
[tool.uv]
dev-dependencies = [
"pytest>=8.0.0",
"ruff>=0.8.0",
"mypy>=1.11.0",
]
The uv.lock File: Reproducible Environments
When you run uv add or uv sync, uv creates a uv.lock file in your project root. This lock file pins the exact versions of every package in your dependency tree — including transitive dependencies.
# Sync your environment to match uv.lock
uv sync
# Sync including dev dependencies (default)
uv sync --dev
# Sync only production dependencies
uv sync --no-dev
# Update all dependencies to latest compatible versions
uv lock --upgrade
# Upgrade a specific package
uv lock --upgrade-package fastapi
Always commit uv.lock to version control. This ensures that every developer on your team, and every CI run, gets exactly the same package versions.
How uv.lock Differs from requirements.txt
| Feature | requirements.txt | uv.lock |
|---|---|---|
| Human-readable | Yes | Yes |
| Includes transitive deps | No (unless pip freeze) | Yes |
| Cross-platform safe | Partial | Yes (platform markers) |
| Managed automatically | No | Yes |
| Conflict detection | No | Yes |
uv Workspaces: Managing Monorepos
If you have a monorepo with multiple Python packages, uv workspaces let you manage them as a unified project with shared dependencies.
# Root pyproject.toml
[tool.uv.workspace]
members = ["packages/*", "apps/*"]
my-monorepo/
├── pyproject.toml # Root workspace config
├── uv.lock # Single shared lockfile
├── packages/
│ ├── core/
│ │ └── pyproject.toml
│ └── utils/
│ └── pyproject.toml
└── apps/
└── api/
└── pyproject.toml
# Run a command in a specific workspace member
uv run --package api python -m uvicorn main:app
# Sync all workspace members
uv sync --all-packages
# Add a cross-workspace dependency
uv add --package api core
Running Scripts with uv run
One of uv's most powerful features is the ability to run Python scripts with inline dependencies, without manually creating a virtual environment first.
Basic Usage
# Run a script using the project's virtual environment
uv run python main.py
# Run a module
uv run python -m pytest
# Run a tool (like a CLI app)
uv run ruff check .
uv run mypy .
Inline Script Dependencies
You can embed dependency requirements directly in a script file using PEP 723 syntax:
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "httpx",
# "rich",
# ]
# ///
import httpx
from rich import print
response = httpx.get("https://api.github.com/repos/astral-sh/uv")
print(response.json()["stargazers_count"])
# Run it — uv installs dependencies automatically in an isolated env
uv run fetch_stars.py
This replaces the common pattern of creating a throwaway virtual environment for one-off scripts.
Migrating from pip, pip-tools, and Poetry to uv
From pip + requirements.txt
If you have an existing requirements.txt:
# Install from existing requirements.txt (no change needed)
uv pip install -r requirements.txt
# Convert to a proper project
uv init
uv add $(cat requirements.txt | grep -v '^#' | tr '\n' ' ')
From pip-tools (requirements.in → requirements.txt)
# Compile is now handled by uv pip compile
uv pip compile requirements.in -o requirements.txt
# Or better yet, migrate to uv's native project management
uv init
uv add -r requirements.in
From Poetry
uv can import a Poetry project's pyproject.toml directly in most cases, since both use the same standard format:
# In your existing Poetry project
uv sync # uv reads [tool.poetry.dependencies] as a fallback
# Fully migrate: export from Poetry first
poetry export -f requirements.txt --output requirements.txt
uv init --name $(cat pyproject.toml | grep "^name" | cut -d'"' -f2)
uv add -r requirements.txt
For most projects, the migration is as simple as replacing poetry run with uv run and poetry install with uv sync.
uv in CI/CD: GitHub Actions Integration
uv is extremely fast in CI/CD environments because of its aggressive caching. Here's how to integrate it into a GitHub Actions workflow:
# .github/workflows/test.yml
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@v4
with:
version: "latest"
enable-cache: true
- name: Set up Python
run: uv python install
- name: Install dependencies
run: uv sync --frozen
- name: Run tests
run: uv run pytest
- name: Lint
run: uv run ruff check .
- name: Type check
run: uv run mypy .
Key CI/CD Tips
--frozen: Useuv sync --frozenin CI to ensure the lock file is respected and never automatically updated.enable-cache: true: Thesetup-uvaction caches the uv cache directory, making subsequent runs significantly faster.- No Python pre-install needed: uv manages Python itself, so you don't need
actions/setup-python.
🔗 See also: Setting Up CI/CD Pipelines with GitHub Actions for Django and FastAPI
uv with FastAPI and Django Projects
Setting Up a FastAPI Project with uv
# Initialize the project
uv init fastapi-app
cd fastapi-app
# Add dependencies
uv add fastapi "uvicorn[standard]" sqlalchemy asyncpg alembic pydantic-settings
# Add development dependencies
uv add --dev pytest pytest-asyncio httpx ruff mypy
# Run the development server
uv run uvicorn app.main:app --reload
Your pyproject.toml:
[project]
name = "fastapi-app"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"fastapi>=0.115.0",
"uvicorn[standard]>=0.32.0",
"sqlalchemy>=2.0.0",
"asyncpg>=0.30.0",
"alembic>=1.14.0",
"pydantic-settings>=2.6.0",
]
[tool.uv]
dev-dependencies = [
"pytest>=8.3.0",
"pytest-asyncio>=0.24.0",
"httpx>=0.28.0",
"ruff>=0.8.0",
"mypy>=1.13.0",
]
Setting Up a Django Project with uv
# Initialize
uv init django-app
cd django-app
# Add dependencies
uv add django djangorestframework psycopg2-binary python-decouple
# Add dev dependencies
uv add --dev pytest pytest-django factory-boy
# Create the Django project
uv run django-admin startproject config .
# Run migrations and server
uv run python manage.py migrate
uv run python manage.py runserver
🔗 See also: Building Your First API with Django: A Beginner's Guide
Dockerfile with uv
uv is also excellent for Docker builds. It can dramatically speed up Docker layer caching:
FROM python:3.12-slim
# Install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
# Copy dependency files first (for layer caching)
COPY pyproject.toml uv.lock ./
# Install dependencies (without project code)
RUN uv sync --frozen --no-install-project
# Copy project code
COPY . .
# Install the project itself
RUN uv sync --frozen
# Run with uv
CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
This approach maximizes Docker layer caching: if only your source code changes (not pyproject.toml or uv.lock), Docker reuses the cached dependency layer.
Conclusion: Should You Switch Today?
Yes. uv has matured rapidly and is production-ready. Here's a quick decision guide:
| Situation | Recommendation |
|---|---|
| New project | Use uv from day one |
| Existing pip project | Migrate gradually — start with uv pip as a drop-in |
| Existing Poetry project | Migrate when you have bandwidth — it's worth it |
| CI/CD pipelines | Switch immediately — the speed gains are dramatic |
| Team project | Migrate together so everyone uses uv sync from the same uv.lock |
uv's approach — a single, fast, opinionated tool — represents the right direction for Python package management. The ecosystem is moving this way, and the sooner you adopt it, the more you'll benefit from the growing ecosystem of uv-native tooling.
🔗 Related: Building a High-Performance Async API with FastAPI and PostgreSQL
📌 Up next: Redis Caching in Django and FastAPI: A Practical Guide