If you've ever sat waiting for pip install to finish building wheels in a Docker build, you know the pain. Five minutes. Ten minutes. Sometimes longer, depending on how many native extensions your project pulls in.

There's a better way. It's called uv, and it's the most talked-about Python tool of 2026 for good reason.

I've been teaching Python to CS students for over a decade, and I've watched pip go from a simple installer to something that can take longer to resolve dependencies than my students' actual code takes to write. uv changes that completely.

If you're looking for a faster pip alternative, uv is your answer — and switching is easier than you think.

Here's what we'll cover:

  • What uv is and why it's 10-100x faster than pip
  • Key features: pip compatibility, venv management, lockfiles, Python version management
  • Migration guide: switching an existing project from pip to uv
  • Docker build comparison — before and after
  • Honest pitfalls: what uv doesn't do (yet)
  • Should you switch? My verdict as a Python teacher and self-hoster

What Is uv?

uv is a Python package and project manager built in Rust by Astral — the same team behind Ruff, the fast Python linter. It replaces pip, pip-tools, pipx, poetry, pyenv, and virtualenv with a single binary.

Install it once, and you get:

  • uv pip install — a drop-in for pip, but 10-100x faster
  • uv venv — create virtual environments
  • uv add / uv remove — add and remove dependencies (like Poetry)
  • uv lock / uv sync — lockfile-based dependency management
  • uv run — run commands in the project environment
  • uv python install — download and manage Python versions (like pyenv)
  • uv tool install / uvx — run tools in isolated environments (like pipx)

One tool. One binary. No more juggling five different package managers.

The Speed Difference Is Real

I'm not going to throw around theoretical benchmarks. Here's what I measured on my setup (BMAX Pro 8, i7 Iris Xe, 24GB RAM):

Scenario pip uv Speedup
Flask + pandas cold install 47s 3.2s ~15x
Django + celery + redis cold install 82s 4.1s ~20x
Resolve dependencies (Trio project) 12s 0.3s ~40x
Install from lockfile (no resolution) 35s 1.8s ~19x

The numbers speak for themselves. uv's Rust-based resolver (using a PubGrub algorithm) is genuinely faster than pip's backtracking resolver.

uv vs pip speed benchmark comparison showing 15-40x speedup across 4 scenarios

Why does this matter? In CI/CD pipelines and Docker builds, every second adds up. A Docker build that takes 5 minutes for pip installs drops to under 30 seconds with uv. If you rebuild containers regularly (which you should), that's hours saved per month.

Installation

Installing uv is straightforward. The recommended way is the standalone installer:

curl -LsSf https://astral.sh/uv/install.sh | sh

This installs uv and uvx to ~/.cargo/bin. No Python required — uv is a standalone Rust binary.

Alternatively, if you already have pip:

pip install uv

Or on macOS/Linux with Homebrew:

brew install uv

Once installed, verify it works:

uv --version

If you see uv 0.11.17 or later, you're good to go.

Migration Guide: Switching an Existing Project

Let's walk through migrating a real project from pip to uv. I'll use a typical CS student project — a Flask web app with pandas and some data processing.

Before (with pip)

Your project probably has a requirements.txt and a workflow like this:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python app.py

Step 1: Create the project config

cd my-project
uv init

This creates a pyproject.toml file. If you already have one, uv will detect it.

Step 2: Import existing dependencies

uv add -r requirements.txt

This reads your requirements.txt, resolves everything with uv's super-fast resolver, and adds each entry to pyproject.toml. It also generates a uv.lock file — the cross-platform lockfile.

Step 3: Verify it works

uv sync
uv run python app.py

That's it. uv sync creates the virtual environment (no separate venv command needed) and installs everything. uv run python app.py runs your script in that environment.

The New Workflow

Once you've migrated, your daily workflow looks like this:

Task Old (pip) New (uv)
Create venv python -m venv .venv && source .venv/bin/activate uv venv
Install dependencies pip install -r requirements.txt uv sync
Add a package pip install flask && pip freeze > requirements.txt uv add flask
Remove a package pip uninstall flask && pip freeze > requirements.txt uv remove flask
Run a script source .venv/bin/activate && python script.py uv run python script.py
Run a tool pip install ruff && ruff check . uvx ruff check .

Notice what's gone: no more source activate, no more manually updating requirements.txt, no more pip freeze. uv handles all of that.

uv migration workflow from pip showing the step-by-step migration process

Docker Build: Before vs After

This is where uv really shines. Let me show you the difference with a real Dockerfile.

Before (pip)

FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "app.py"]

Build time: ~4-5 minutes. Every code change rebuilds from scratch because the requirements layer is thin and pip doesn't cache well in Docker.

After (uv)

FROM python:3.12-slim

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app

COPY pyproject.toml uv.lock ./
RUN uv sync --locked --no-install-project

COPY . .
RUN uv sync --locked

CMD ["uv", "run", "python", "app.py"]

Build time: ~30-45 seconds. Here's why:

  • Layer 1 (lock files only): cached unless pyproject.toml or uv.lock changes
  • Layer 2 (project code): only rebuilds when your source files change
  • Cache mounts (optional but recommended): uv's global cache persists across builds

For even faster builds with cache persistence:

FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app

ENV UV_LINK_MODE=copy \
    UV_COMPILE_BYTECODE=1

COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --locked --no-install-project

COPY . .
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --locked

CMD ["uv", "run", "python", "app.py"]

The UV_LINK_MODE=copy flag ensures cross-filesystem compatibility in multi-stage builds, and UV_COMPILE_BYTECODE=1 pre-compiles .pyc files for faster startup.

Dockerfile before and after switching to uv showing pip vs uv Docker build comparison

uv's Built-in Python Version Management

Here's a feature I wish I'd had when teaching. uv can download and manage Python versions automatically:

# List available Python versions
uv python list

# Install Python 3.12
uv python install 3.12

# Install multiple versions at once
uv python install 3.12 3.13 3.14

# Pin a version for your project
echo "3.12" > .python-version

This means my students no longer need to install Python separately, then pip, then venv. A single curl | sh for uv gives them everything. For Cambridge CS students working on exam prep, this is a game-changer — fast environment setup means more time actually coding.

One correction to the common myth: uv fully supports Python 3.12, 3.13, and even 3.14. If you've heard otherwise, that information is outdated. uv v0.11.17 (released May 2026) can install and manage Python 3.8 through 3.15.

Honest Pitfalls: What uv Doesn't Do (Yet)

I've been using uv for a few months now, and while I'm convinced it's the better tool, I want to be honest about the rough edges.

1. uv Doesn't Read pip.conf

If you have a corporate proxy or custom index configured in pip.conf or PIP_INDEX_URL, uv won't pick it up. You need to use UV_INDEX_URL or configure it in pyproject.toml:

[tool.uv.pip]
index-url = "https://your-private-index.com/simple"

2. Stricter Pre-release Handling

uv requires explicit opt-in for pre-release dependencies in transitive packages. Pip is more lenient. If you hit resolution errors, try:

uv sync --prerelease allow

3. PEP 517 Build Isolation

Some older packages that don't support PEP 517 build isolation will fail. The workaround is:

uv pip install --no-build-isolation stubborn-old-package

4. venv-first by Default

uv pip install installs into the nearest .venv directory by default. If you want to install globally (which I don't recommend), use --system:

uv pip install --system some-package

5. Different Resolver, Different Results

uv uses a PubGrub resolver (same algorithm as Dart's pub and Rust's cargo), while pip uses a backtracking resolver. They'll usually produce the same result, but not always. If you're migrating a complex project, run uv lock and check the resolution carefully.

Should You Switch?

Short answer: Yes.

Long answer: If you're a CS student starting a new Python project, start with uv. Don't install pip separately. If you're a developer managing multiple projects, switch your active projects and keep pip around for legacy ones. If you're building Docker images, switching to uv will save you hours per month.

The only case I'd hold off on switching is if you maintain a package that needs to support very old toolchains — uv's stricter dependency resolution might surface issues you'd rather not deal with. But even then, uv's pip-compatible mode (uv pip install) works for most cases.

I switched my own projects — including the scripts I use for running this blog and my teaching materials — and I'm not looking back. The time savings alone are worth it, and the unified tooling (Python versions, venvs, packages, lockfiles, tools) makes my workflow simpler, not more complex.

Quick Start

If you want to try it right now:

curl -LsSf https://astral.sh/uv/install.sh | sh
cd my-python-project
uv init
uv add flask pandas
uv run python app.py

That's four commands to go from zero to running with uv.

If you're new to Python, start with my

Python Programming Setup Guide for 2026
Python Programming Setup Guide for 2026 So you want to learn Python. Great choice — Python’s been the fastest-growing major programming language for…

If indentation and syntax are tripping you up, read

Why use indentation in Python
Indentation is an important concept to understand in Python, if you are not indenting your Python code properly, you will end up getting the…

it's a common source of confusion for beginners switching tools. For a full development environment, check out

Setting Up a Python Development Environment on VirtualBox with Ubuntu (2026 Edition)
I’ve been using VirtualBox for development environments for years. The beauty of it is isolation — your host machine stays clean, you can blow away

Have you tried uv yet? What's your experience been? Drop a comment below or reach out — I'd love to hear how the migration went for you.

Techie Mike
Techie Mike
Computer Science teacher in Thailand. 10+ years Cambridge IGCSE, 4 years AS/A Level. BSc Computer Science & Engineering. Ex-Intel, Virgin Media. Practical exam prep, past paper walkthroughs and tech tutorials.