uv#
uv isn't "faster pip." it's cargo for python - a unified toolchain that changes what's practical to do.
install#
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
the commands you actually use#
uv sync # install deps from pyproject.toml
uv run pytest # run in project environment
uv add httpx # add a dependency
uvx ruff check # run a tool without installing it
never use uv pip. that's the escape hatch, not the workflow.
zero-setup environments#
run tools without installing anything:
uvx flask --help
uvx ruff check .
uvx pytest
this creates an ephemeral environment, runs the tool, done. no virtualenv activation, no pip install.
the repro pattern#
testing specific versions without polluting your environment:
# test against a specific version
uv run --with 'pydantic==2.11.4' repro.py
# test a git branch before it's released
uv run --with pydantic@git+https://github.com/pydantic/pydantic.git@fix-branch repro.py
# combine: released package + unreleased fix
uv run --with prefect==3.1.3 --with pydantic@git+https://github.com/pydantic/pydantic.git@fix repro.py
for monorepos with subdirectories:
uv run --with git+https://github.com/prefecthq/prefect.git@branch#subdirectory=src/integrations/prefect-redis repro.py
inline script metadata#
PEP 723 lets you embed dependencies directly in a script:
# /// script
# dependencies = ["httpx", "rich"]
# requires-python = ">=3.12"
# ///
import httpx
from rich import print
print(httpx.get("https://httpbin.org/get").json())
run with uv run script.py - uv reads the metadata and creates an environment with those dependencies. no pyproject.toml, no requirements.txt, just a self-contained script.
this is how you share reproducible examples. put the dependencies in the file itself, and anyone with uv can run it.
shareable one-liners#
no file needed:
uv run --with 'httpx==0.27.0' python -c 'import httpx; print(httpx.get("https://httpbin.org/get").json())'
share in github issues, slack, anywhere. anyone with uv can run it.
stdin execution#
pipe code directly:
echo 'import sys; print(sys.version)' | uv run -
pbpaste | uv run --with pandas -
project workflow#
uv init myproject # create new project
cd myproject
uv add httpx pydantic # add deps
uv sync # install everything
uv run python main.py # run in environment
uv sync reads pyproject.toml and uv.lock, installs exactly what's specified.
why this matters#
the old way:
- install python (which version?)
- create virtualenv
- activate it (did you remember?)
- pip install (hope versions resolve)
- run your code
the uv way:
uv run your_code.py
uv handles python versions, environments, and dependencies implicitly. you stop thinking about environment management.
sources: