DEV Community

Cover image for Stop Juggling 5 Tools , Python's uv Does It All (And It's Blazing Fast)
Shayan Holakouee
Shayan Holakouee

Posted on

Stop Juggling 5 Tools , Python's uv Does It All (And It's Blazing Fast)

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Verify:

uv --version
# uv 0.9.x
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

That single command gives you:

my-api/
├── .git/
├── .venv/          ← already created
├── .python-version
├── pyproject.toml
├── README.md
└── main.py
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 .
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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]")
Enter fullscreen mode Exit fullscreen mode

Run it with:

uv run my_script.py
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen 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
Enter fullscreen mode Exit fullscreen mode

Each layer has its own state, its own config, its own failure modes.

With uv, the mental model is much flatter:

uv → everything
Enter fullscreen mode Exit fullscreen mode

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)