UV: Modern Python Package Manager That's 10-100x Faster
Managing Python dependencies has always been a challenge. We need to install pip, virtualenv, pyenv, and poetry separately, then configure each tool individually. UV arrives as an all-in-one solution that replaces all these tools with 10-100x faster performance. Written in Rust by the Astral team (creators of Ruff), UV is a next-generation Python package manager that transforms how we work with the Python ecosystem.
In this tutorial, we will learn UV comprehensively from installation, project management, virtual environments, to a practical example of building an ML project from scratch.
Why UV?
Before diving into the technical details, let's understand why UV is worth considering:
- Exceptional speed: 10-100x faster than pip thanks to Rust implementation and global caching
- All-in-one: Replaces pip, pip-tools, virtualenv, pyenv, and poetry in a single binary
- Built-in lockfile: Reproducible builds without additional configuration
- Python version management: Install and switch Python versions without pyenv
- Cross-platform: Works consistently on Linux, macOS, and Windows
- Drop-in replacement: Compatible with the existing pip ecosystem
Installing UV
Linux and macOS
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Using pip (alternative)
pip install uv
Using Homebrew (macOS)
brew install uv
Verify the installation:
uv --version
Updating UV
uv self update
Creating Projects with uv init
UV provides an easy way to start new Python projects:
uv init my-project
cd my-project
This command creates the following project structure:
my-project/
├── .python-version
├── README.md
├── hello.py
└── pyproject.toml
The generated pyproject.toml:
[project]
name = "my-project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
Initialization Options
# Create project as a library (with src layout)
uv init --lib my-library
Create project as an application
uv init --app my-app
Specify minimum Python version
uv init --python 3.11 my-project
Create project in current directory
uv init
For library projects, the structure will be different:
my-library/
├── .python-version
├── README.md
├── pyproject.toml
└── src/
└── mylibrary/
├── init.py
└── py.typed
Dependency Management
Adding Dependencies
# Add a package
uv add requests
Add with specific version constraints
uv add "pandas>=2.0,<3.0"
Add multiple packages at once
uv add numpy scikit-learn matplotlib
Add development dependency
uv add --dev pytest ruff mypy
Add optional dependency group
uv add --group docs sphinx sphinx-rtd-theme
Each time you run uv add, UV will automatically:
pyproject.tomluv.lockRemoving Dependencies
# Remove a package
uv remove requests
Remove a dev dependency
uv remove --dev mypy
Viewing the Dependency Tree
uv tree
Example output:
my-project v0.1.0
├── numpy v1.26.4
├── pandas v2.2.1
│ ├── numpy v1.26.4
│ ├── python-dateutil v2.9.0
│ │ └── six v1.16.0
│ ├── pytz v2024.1
│ └── tzdata v2024.1
└── scikit-learn v1.4.1
├── joblib v1.3.2
├── numpy v1.26.4
├── scipy v1.12.0