If you've been writing Python for more than a year, you know the ritual. A new project. A fresh terminal. And then:
pyenv install 3.12.3
pyenv local 3.12.3
python -m venv .venv
source .venv/bin/activate
pip install pip --upgrade
pip install -r requirements.txt
Six commands before you've written a single line of code. And that's if nothing breaks.
Enter uv a single binary that replaces pip, virtualenv, pip-tools, pyenv, and pipx. Written in Rust. 10–100x faster than pip. And honestly, one of the most pleasant tools I've used in the Python ecosystem in years.
Let's dig into it.
What Even Is uv?
uv is a Python package and project manager built by Astral, the same team behind ruff, the linter that everyone switched to and never looked back. The goal is simple: be the Cargo for Python. One tool, one lockfile, no friction.
It's a standalone binary with zero Python dependencies, which means it works even before Python is installed.
Installing uv
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Or via pip if you prefer
pip install uv
Verify:
uv --version
# uv 0.9.x
The Speed Claim Is It Real?
Yes. Embarrassingly so.
Here's a timed comparison on Apple Silicon (Python 3.14):
| Operation |
pip / venv
|
uv |
|---|---|---|
| Create virtual env | ~2 seconds | 35 milliseconds |
| Install FastAPI + deps (cold) | ~12s | ~1.2s |
| Install with warm cache | ~8s | ~0.1s |
The warm cache case is where uv really shines it uses a global cache and hard-links packages into environments instead of copying them. If you've installed requests in any previous project, your next project gets it nearly instantly.
Starting a New Project
This is where uv feels like a completely different world:
uv init my-api
cd my-api
That single command gives you:
my-api/
├── .git/
├── .venv/ ← already created
├── .python-version
├── pyproject.toml
├── README.md
└── main.py
No separate python -m venv, no git init, no template copying. It's all there.
Managing Python Versions
Before uv, this meant pyenv. Now:
# Install any Python version
uv python install 3.12
# Pin a version for the current project
uv python pin 3.11
# List installed versions
uv python list
uv manages its own Python installations, independently of whatever system Python you have. No more which python3 confusion.
Adding and Removing Dependencies
# Add a package (updates pyproject.toml + uv.lock)
uv add fastapi
# Add a dev-only dependency
uv add --dev pytest ruff
# Remove a package
uv remove requests
# Sync your environment to match the lockfile
uv sync
Notice what's missing: no pip install, no pip freeze > requirements.txt, no manually editing pyproject.toml. uv add handles all of it atomically.
The uv.lock file is cross-platform and cross-Python-version one lockfile that works for your whole team regardless of OS.
Running Commands Without Activating the Venv
This is a small thing that makes a big difference in practice:
# Instead of: source .venv/bin/activate && python main.py
uv run main.py
# Run a dev tool
uv run pytest
# Run ruff
uv run ruff check .
uv run automatically uses the project's virtual environment. You never have to think about activation again.
Replacing pipx Running One-off Tools
pipx lets you run CLI tools in isolated environments. uv does this too:
# Run a tool without installing it globally
uvx ruff check .
uvx black --check src/
# Or install it as a persistent tool
uv tool install httpie
uvx is the npx of Python. Run a tool once, don't pollute your environment.
Inline Script Dependencies
This is a lesser-known feature that's actually great for scripting:
# /// script
# requires-python = ">=3.11"
# dependencies = ["httpx", "rich"]
# ///
import httpx
from rich import print
response = httpx.get("https://api.github.com/zen")
print(f"[bold green]{response.text}[/bold green]")
Run it with:
uv run my_script.py
uv reads the inline metadata, creates a temporary isolated environment, installs httpx and rich, and runs the script. No manual setup. Perfect for one-off automation scripts you share with teammates.
Migrating an Existing Project
Already have a requirements.txt or a Poetry project? Migration is low-friction:
# From requirements.txt
uv init
uv add $(cat requirements.txt)
# Or import directly
uv pip install -r requirements.txt # pip-compatible mode
uv also has a pip-compatible interface (uv pip install, uv pip freeze, etc.) for teams that want the speed gains without changing their workflow immediately.
The Mental Model Shift
Here's the thing that took me a moment to internalize. With traditional Python tooling, you manage layers:
pyenv → Python version
venv → Isolated environment
pip → Package installation
pip-tools → Lockfile generation
pipx → Global tool isolation
Each layer has its own state, its own config, its own failure modes.
With uv, the mental model is much flatter:
uv → everything
One tool manages Python versions, environments, dependencies, lockfiles, and tool execution. The cognitive overhead just... goes away.
When to Still Be Careful
uv is production-ready but worth knowing its quirks:
- Conda environments: uv doesn't replace conda. If you're in data science and relying on conda for native packages or CUDA builds, uv isn't a full substitute yet.
- Complex build requirements: Packages that need special compilers or system libs work fine, but you'll need those system deps present just like with pip.
- It's still pre-1.0: uv is at ~0.9.x. The API is stable for daily use, but if you're building enterprise tooling around it, keep an eye on the changelog.
The Bottom Line
uv is the Python tooling reset the ecosystem needed. It's not experimental it's fast, pragmatic, and genuinely replaces a stack of tools that have been awkward to use together for years.
For new projects: start with uv init. You won't miss the old way.
For existing projects: try swapping in uv pip install for pip first. It's a one-character change and you'll immediately notice the speed difference. From there, adopting the full workflow is a natural next step.
If you found this useful, drop a ❤️ or share it with someone still writing six commands to start a project. The uv docs at docs.astral.sh/uv are genuinely excellent if you want to go deeper.
Top comments (0)