Using uv

It makes Python packaging work

The only Python packaging system I've ever recommended

 

Andy Casey
with help from Lehman Garrison

What is uv?

  • Extremely fast package and project manager
  • Written in 🦀 Rust by Astral (creators of Ruff)
  • Replaces pip, pip-tools, pipx, poetry, pyenv, virtualenv, and more
  • 10-100x faster than pip for package installation
  • Strives for reproducible installations
  • Solves the Python packaging problem 👀

Great, Another Python Package Manager 🫠

Real Technical Innovation

Smart Package Caching with Symlinks

  • uv maintains a global package cache
  • Uses hard links to existing installations when constraints match
  • Creating a new venv with the same packages? Nearly instant!
  • Storage overhead? Essentially zero for duplicate packages

No more downloading and installing the same package versions

Real Technical Innovation

Integer-Based Version Resolution

  • uv assigns integer IDs to package versions
  • Enables ultra-fast version comparisons and constraint solving
  • Dependency resolution becomes a high-performance graph problem
  • This is why it's 10-100x faster

conda might parse (m|b)illions of version string comparisons during resolution

Learning from History

  • conda tried to solve a different problem to pip
  • Both were (rightly) constrained by wanting to avoid breaking changes
  • Stifled innovation, in part Python is not a good tool to manage Python
  • conda caused community friction with licensing concerns
  • uv has a different approach...

Truly Open Source

  • MIT/Apache 2.0 licensed - no strings attached
  • Fully open source on GitHub
  • Made by Astral, but community-driven
  • No hidden costs, no license concerns
  • Transparent development and governance
  • Not reliant on using Astral servers

Astral could disappear today and Python packaging would still be a solved problem (which I thought would never happen!)

Why Use uv?

  • It's quick: 101-106 times faster than other tools
  • 🔒 Reproducible: Lock files help with consistency
  • 🛠️ All-in-one: Replaces multiple tools
  • 🐍 Python management: Install and manage Python versions
  • 📦 Modern workflow: Built for common setups
  • 🦀 Rust-powered: Reliable and efficient
  • 🚀 Responsive team: One of many Astral tools

Speed Comparison

Task Traditional Tool uv Speedup
Install packages pip uv pip install 10-100x
conda uv pip install Up to 106
Create venv python -m venv uv venv 80x
Resolve deps pip-tools uv lock 10-100x
Run tools pipx uvx Faster

Installation

Install uv with a single command:


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

# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

# With pip
pip install uv

# With Homebrew
brew install uv
                

Create a Virtual Environment

Create a virtual environment:


> uv venv

# uv will detect and use this environment
> uv pip install numpy

> uv run python
                

uv automatically detects and uses the virtual environment

Installing Packages


# Install a package
uv pip install requests

# Install multiple packages
uv pip install requests pandas numpy

# Install from requirements.txt
uv pip install -r requirements.txt

# Install with specific version
uv pip install "django>=4.0,<5.0"
                

Managing Python Versions

uv can install and manage Python itself!


# List available Python versions
uv python list

# Create a venv with a specific Python version
uv venv -p 3.14

# uv auto-installs missing Python versions as needed
                

Project Management


# Initialize a new project
uv init my-project
cd my-project

# Add a dependency (updates pyproject.toml)
uv add requests

# Remove a dependency
uv remove requests

# Sync environment with project dependencies
uv sync
                

Version Pinning

uv creates lock files to avoid version mis-matches


# Generate/update lock file
uv lock

# Install from lock file (exact versions)
uv sync

# This ensures everyone gets the same dependencies!
                

This doesn't guarantee reproducible installations, but it does minimise chances of version mis-matches.

Running Scripts


# Run a Python script with dependencies
uv run script.py

# Run a module
uv run -m pytest

# Run inline script with dependencies
uv run --with requests python -c \
"
import requests as r
print(r.get('https://api.github.com').json())
"

# Execute a package (like pipx)
uvx ruff check .
                

Run Tools Without Installing

Use uvx to instantly run any Python tool from PyPI:


            # Run a tool you've never installed
            ❯ uvx pycowsay hello from uv
            Installed 1 package in 3ms

              -------------
            < hello from uv >
              -------------
               \   ^__^
                \  (oo)\_______
                   (__)\       )\/\
                       ||----w |
                       ||     ||
                                        

uv creates a temporary venv, installs the package, and runs it!

Run Tools Without Installing

Use uvx to instantly run any Python tool from PyPI:


# Run a tool you've never installed
uvx ruff check .

# Run a specific version
uvx black@23.0.0 myfile.py

# Run with arguments
uvx httpie https://api.github.com
                

Useful if you want to try something without contaminating one of your existing environments.

Single-File Scripts

Manage dependencies in standalone scripts:


# /// script
# requires-python = ">=3.12"
# dependencies = [
#     "requests",
#     "rich",
# ]
# ///

import requests
from rich import print

response = requests.get("https://api.github.com")
print(response.json())
                

uv run script.py  # Auto-installs dependencies!
                

Other Useful Commands


# List installed packages
uv pip list

# Show package info
uv pip show requests

# Compile requirements (like pip-compile)
uv pip compile pyproject.toml -o requirements.txt

# Upgrade packages
uv pip install --upgrade requests

# See dependency tree
uv tree
                

How I Use uv

Real-world workflow examples

On My Laptop: Science Projects


# An existing project with a pyproject.toml file
cd my_project/
uv sync

# A new project
uv init my_new_project
cd my_new_project/
uv add numpy matplotlib scipy
                
  • Each project has its own virtual environment
  • Project-specific dependencies and versions
  • Reproducible environments with lock files
  • Easy to share and collaborate

Protects Me From Silly Mistakes


$ cd some_folder
$ uv add strict_versions_and_big_dependency_graph
error: No virtual environment found; run `uv venv` to create an environment,
       or pass `--system` to install into a non-virtual environment

$ python
zsh: command not found: python

$ which python
python not found
                

I have no global python installed!

Either I'm in the wrong directory, or I haven't created an environment for this project yet.

My Scratch Environment

  • Top-level virtual environment in ~/research/
  • General-purpose stack with most tools I need
  • Don't care about specific versions
  • It's okay if it breaks - just recreate it!
  • Perfect for quick experiments and testing ideas

Another Scratch Approach:

Manage dependencies in standalone scripts:


            # /// script
            # requires-python = ">=3.12"
            # dependencies = [
            #     "requests",
            #     "rich",
            # ]
            # ///

            import requests
            from rich import print

            response = requests.get("https://api.github.com")
            print(response.json())
                            

            uv run script.py
                            

On Flatiron Clusters

Load uv using the module system:


module load uv python
                

As per the docs, this will set

UV_CACHE_DIR=$HOME/.cache/uv

because your virtual environments should be in $HOME and not ceph, and uv's file linking strategy only works within a filesystem.

On Flatiron Clusters

You want:

  1. Code stored in home directory sub-folders
  2. Use the system-wide built libraries on rusty
    • jax, torch, etc
  3. Data stored on ceph, linked from your home directory

Quick Start Guide


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

# 2. Create a new project
uv init my-app && cd my-app

# 3. Add dependencies
uv add requests pandas

# 4. Run your code
uv run main.py

# That's it! 🎉
                

Resources



Thank You! 🚀