Chapter 7, Environment
uv: the unified manager
The uv installs Python versions, creates environments, resolves dependencies, runs scripts, and installs tools, all in a single very fast binary. It is what I use by default in new projects.
This chapter uses terminal commands. The files for this chapter are in exemplos/.
Why I use uv
The uv is made by Astral (the creators of ruff) and written in Rust. What convinced me was the combination of three things: it replaces pyenv, venv, pip, pipx and a good part of Poetry; it downloads ready-made Pythons instead of compiling; and it has a pip-compatible interface for when you already have a setup.
Install
curl -LsSf https://astral.sh/uv/install.sh | sh
With Homebrew: brew install uv.
It is also possible to install with pipx install uv or pip install uv. If you installed via the official installer, update with:
uv self update
Manage Python versions
The uv downloads and keeps the versions you request. No compiler or previous Python is needed:
uv python install 3.12 3.13 3.14
uv python list
uv python pin 3.13
The uv python pin writes the file .python-version in the folder, the same file that pyenv uses.
Create and manage a project
uv init meu-app
cd meu-app
uv add requests
uv add --dev pytest
uv run python main.py
uv run pytest
The uv add changes the pyproject.toml and updates the file uv.lock. The uv run ensures that the environment exists and is up to date before executing, so you don't need to activate anything. The pyproject.toml looks like this:
[project]
name = "meu-app"
version = "0.1.0"
description = "Exemplo de projeto gerenciado pelo uv"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"requests>=2.34.2",
]
[dependency-groups]
dev = [
"pytest>=9.1.1",
]
Other commands that I use all the time:
uv remove requests
uv sync
uv lock
uv tree
Scripts with embedded dependencies
For a standalone script that needs a library, uv accepts metadata in the file itself (a standard called PEP 723). It creates a temporary environment just for that execution:
# /// script
# requires-python = ">=3.12"
# dependencies = ["rich"]
# ///
from rich import print
print("[bold]Olá[/bold] de um script com dependências embutidas")
uv run exemplos/uv/script_inline.py
To add a dependency to an existing script: uv add --script script.py requests.
Command line tools
uv tool install ruff
uvx ruff check .
uv tool list
uv tool upgrade --all
The uvx is a shortcut for uv tool run: runs the tool in a temporary environment, like pipx run.
Compatibility with pip
If you already have requirements.txt and don't want to migrate now, use the compatible interface:
uv venv
uv pip install -r requirements.txt
uv add versus uv pip install
The
uv addregisters the dependency inpyproject.tomland in the lockfile. Theuv pip installonly installs in the environment, in pip style, and does not register anything. Mixing the two in the same project is the most common cause of "it works on my machine".