43.6 uv: The Fastest Package Installer
uv is a blisteringly fast Python package installer and resolver, written in Rust, designed as a drop-in replacement for pip and pip-tools. It serves as the backbone for the next-generation Python package manager, Rye, but is a powerful standalone tool. Its primary value proposition is speed, often achieving performance an order of magnitude greater than traditional tools by leveraging a highly parallelized architecture and a global, persistent cache.
Core Installation and Setup
uv can be installed standalone or as part of Rye. The most direct method is via curl:
curl -LsSf https://astral.sh/uv/install.sh | sh
This installs uv into ~/.cargo/bin by default. On Windows, you can use powershell:
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
Once installed, you can begin using it immediately. Its CLI is designed to be familiar to pip users, significantly lowering the adoption barrier. You can verify the installation and check the version with:
uv --version
Basic Package Management Commands
The core workflow for installing packages mirrors pip almost exactly. To install a single package, such as requests, into your current environment:
uv pip install requests
The pip subcommand is used to indicate that you are performing pip-compatible operations. To install multiple packages and their dependencies:
uv pip install requests httpx beautifulsoup4
The speed difference here is immediately apparent; uv resolves dependencies and downloads wheels in parallel, utilizing a shared global cache. This means if you’ve ever installed requests in any project or environment on your system, subsequent installs are nearly instantaneous as uv will reuse the cached wheel.
Uninstalling a package is equally straightforward:
uv pip uninstall httpx
Dependency Resolution and the Lockfile
A critical feature of uv is its robust and extremely fast dependency resolver. Unlike pip’s resolver, which can be slow and sometimes backtrack endlessly, uv uses a modern, PubGrub-based resolver. This results in faster, more correct resolutions, especially for complex dependency graphs.
To generate a lockfile (uv.lock) from a requirements.in or pyproject.toml file, you use the uv lock command. This is the equivalent of pip-compile from pip-tools.
# If you have a requirements.in file
uv lock -r requirements.in
# Or, to read from a pyproject.toml (like with Rye or a PEP 621 project)
uv lock
The resulting uv.lock file contains all primary and transitive dependencies pinned to exact versions, ensuring reproducible installs across different systems. You can then install from this lockfile:
uv sync
The uv sync command is a best practice. It doesn’t just install packages; it synchronizes your environment to exactly match the lockfile. If a package is present in the environment but not in the lockfile, uv sync will remove it. This guarantees environment parity, a common pitfall where developers use pip install -r requirements.txt but have stray packages causing “but it works on my machine” issues.
Advanced Usage: Creating Virtual Environments
While uv can install packages into any existing environment (by using the --python flag to point to it), it excels at creating and managing its own virtual environments. The uv venv command creates a new virtual environment.
# Create a virtual environment named `.venv`
uv venv
# Create a virtual environment with a specific Python version
uv venv --python 3.11
# Create a virtual environment with a specific name
uv venv my_env
The key advantage here is speed. uv does not simply call the standard library’s venv module; it implements its own virtual environment creation logic, making it significantly faster. After creating an environment, you can activate it as usual or have uv run commands inside it directly using uv run.
# Activate on Unix/macOS
source .venv/bin/activate
# Activate on Windows
.venv\Scripts\activate
# Or, run a command directly inside the environment without activation
uv run python script.py
uv run pytest
Integration with pyproject.toml and Best Practices
uv is built for the modern Python ecosystem and has first-class support for pyproject.toml (PEP 621). The optimal workflow involves using uv alongside a pyproject.toml file that defines your dependencies.
- Define your dependencies: List your main dependencies in the
project.dependenciessection of yourpyproject.toml.[project] name = "my-project" version = "0.1.0" dependencies = [ "requests>=2.28.0", "httpx", ] - Generate the lockfile: Run
uv lockto resolve all dependencies and create auv.lockfile. - Synchronize the environment: Run
uv syncto create a virtual environment (if it doesn’t exist) and install all packages from the lockfile into it. This is a single, idempotent command that ensures correctness.
This workflow eliminates the need for separate requirements.txt files and ensures that your environment is always a perfect reflection of your declared dependencies and their resolved, compatible versions. It is the most robust way to avoid version conflicts and deployment surprises.