Introducing UV: A Fast Python Package Manager

Introducing UV: A Fast  Python Package Manager
Photo by Timothy Dykes / Unsplash

What is UV?

UV (pronounced "you-vee") is an extremely fast Python package manager and development tool created by Astral, the team behind Ruff. It's designed to replace multiple Python development tools with a single, unified, high-performance solution.

Key Features

  • All-in-One Solution: UV replaces multiple tools including:
    • pip for package installation
    • pip-tools for dependency management
    • pipx for tool management
    • poetry for project management
    • pyenv for Python version management
    • twine for package publishing
    • virtualenv for environment management
  • Performance: UV executes 10-100x faster than pip, making package installations and dependency resolutions significantly quicker.
  • Python Version Management: Built-in capability to install and manage multiple Python versions, allowing easy switching between versions for different projects.
  • Universal Project Management: Features a comprehensive project management system with universal lockfile support.
  • Resource Efficient: Uses a global cache for dependency deduplication, making it disk-space efficient.

Comparison with Existing Tools

While other tools specialize in specific aspects of Python development, UV consolidates these functionalities:

Feature Traditional Approach UV Approach
Package Installation pip uv pip install
Virtual Environments virtualenv/venv uv venv
Python Version Management pyenv uv python
Project Management poetry/pipenv uv init/add/remove
Tool Running pipx uvx / uv tool

Why Use UV?

  1. Simplified Workflow: Instead of learning and maintaining multiple tools, you have a single tool with consistent interfaces.
  2. Superior Performance: The dramatic speed improvement over traditional tools means less time waiting for installations and builds.
  3. Space Efficiency: The global cache system prevents duplicate package storage across projects.
  4. Cross-Platform: Works consistently across macOS, Linux, and Windows.
  5. No Dependencies: Can be installed without requiring Rust or Python.

Installation

You can install UV through several methods:

On macOS and Linux:

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

On Windows:

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

Using pip or pipx:

# With pip
pip install uv

# With pipx
pipx install uv

After installation, you can update UV to the latest version using:

uv self update

Platform Support

UV is designed to work across all major operating systems:

  • macOS
  • Linux
  • Windows

Each platform gets full feature support, ensuring a consistent experience regardless of your operating system.


UV Quick Start Guide

This guide will help you get started with UV, covering the basic commands and common workflows you'll need for Python development.

Basic Command Structure

UV uses a consistent command structure:

uv [OPTIONS] <COMMAND>

Common commands include:

  • run: Run a command or script
  • init: Create a new project
  • add: Add dependencies
  • remove: Remove dependencies
  • sync: Update project's environment
  • venv: Create a virtual environment

Global options available for all commands:

  • -q, --quiet: Do not print any output
  • -v, --verbose: Use verbose output
  • --directory: Change to given directory before running command
  • --project: Run command within given project directory

First Project Setup

Let's create and set up your first UV project:

  1. Create a new project:
# Create and enter project directory
uv init myproject
cd myproject
  1. Set up a virtual environment:
uv venv
# On Unix systems, activate with:
source .venv/bin/activate
# On Windows:
# .venv\Scripts\activate
  1. Add some dependencies:
# Add a production dependency
uv add requests

# Add development dependencies
uv add --dev pytest black

Common Workflows

Managing Python Versions

# Install Python versions
uv python install 3.11

# Pin project to specific version
uv python pin 3.11

Running Scripts

# Run a Python script
uv run script.py

# Run a command in the project environment
uv run pytest

Managing Dependencies

# View dependency tree
uv tree

# Update dependencies
uv sync

# Remove a dependency
uv remove requests

Working with Tools

# Run a tool without installing
uvx black myfile.py

# Install a tool globally
uv tool install ruff

Basic Troubleshooting

Here are solutions to common issues you might encounter:

Environment Issues

If you experience environment problems:

# Force create new environment
uv venv --force

Cache Issues

If you encounter cache-related problems:

# Clear the cache
uv cache clean

# Remove outdated entries
uv cache prune

Dependency Resolution Issues

If you have dependency conflicts:

# View dependency tree to identify conflicts
uv tree

# Try updating all dependencies
uv sync --upgrade

Common Error Messages

  1. "Python version not found"
    • Solution: uv python install <version>
  2. "Package not found"
    • Check package name spelling
    • Verify package exists on PyPI
    • Try updating your package index
  3. "Environment already exists"
    • Use --force flag with uv venv
    • Delete existing environment manually

Next Steps

After mastering these basics, you can:

  1. Explore advanced dependency management
  2. Learn about lockfile usage
  3. Set up project configurations
  4. Integrate with CI/CD pipelines

For more detailed information about any command, use:

uv help <command>

Python Version Management with UV

UV provides built-in Python version management, allowing you to install, switch between, and manage multiple Python versions easily. This guide covers everything you need to know about managing Python versions with UV.

Installing Python Versions

UV can install and manage multiple Python versions:

# Install specific Python versions
uv python install 3.10 3.11 3.12

# Install PyPy
uv python install pypy@3.8

# Install exact version
uv python install 3.11.4

You can view available Python versions:

# List installed versions
uv python list

# List available versions for installation
uv python list --available

Switching Between Versions

UV offers several ways to switch between Python versions:

For a Single Command

# Run command with specific Python version
uv run --python 3.11 -- python --version

# Run with PyPy
uv run --python pypy@3.8 -- python --version

For a Project

# Pin project to specific Python version
uv python pin 3.11

# This creates/updates .python-version file

For Virtual Environments

# Create venv with specific Python version
uv venv --python 3.11

Project-Specific Python Versions

UV supports project-specific Python version management through the .python-version file:

  1. Pin a version for your project:
cd myproject
uv python pin 3.11
  1. The .python-version file will be created/updated:
3.11
  1. UV will now use this version for all commands in this directory:
uv run python --version  # Will use Python 3.11

Managing Multiple Installations

UV maintains a central location for installed Python versions:

# View Python installation directory
uv python dir

# Find specific Python version
uv python find 3.11

# Uninstall a version
uv python uninstall 3.11.4

Version Resolution

UV uses the following order to resolve Python versions:

  1. Explicit version specified in command (--python)
  2. Project's .python-version file
  3. System Python installation

You can control this behavior with --python-preference:

# Prefer UV-managed installations
uv --python-preference managed run python --version

# Only use system Python
uv --python-preference only-system run python --version

Advanced Features

Offline Installation

Disable automatic Python downloads:

uv --no-python-downloads run python --version

Custom Installation Location

Change where UV installs Python versions:

UV_PYTHON_PATH=/custom/path uv python install 3.11

Version Constraints

UV supports flexible version specifications:

# Latest 3.11.x release
uv python install 3.11

# Exact version
uv python install 3.11.4

# Latest available
uv python install 3

# Latest PyPy version
uv python install pypy

Best Practices

  1. Version Control: Always commit .python-version to your repository to ensure consistent Python versions across team members.
  2. Virtual Environments: Create new virtual environments when switching Python versions to avoid compatibility issues.
  3. Version Specificity: Be as specific as needed with versions:
    • Use 3 for latest Python 3
    • Use 3.11 for latest Python 3.11.x
    • Use 3.11.4 for exact version
  4. Regular Updates: Periodically check for and install Python updates:
uv python list --available
uv python install 3.11  # Will install latest 3.11.x

Troubleshooting

Common issues and solutions:

  1. Version Not Found
# Update available versions list
uv python list --available --refresh
  1. Installation Fails
# Try with verbose output
uv -v python install 3.11

# Check system requirements
uv python requirements
  1. Version Conflict
# Force reinstall
uv python install --force 3.11

For more detailed information about Python version management, use:

uv help python

Dependency Management with UV

UV provides powerful dependency management capabilities that help you manage your project's dependencies efficiently. This guide covers how to add, remove, and manage dependencies in your Python projects.

Adding Dependencies

UV offers several ways to add dependencies to your project:

Basic Dependency Addition

# Add a single dependency
uv add requests

# Add multiple dependencies
uv add requests pandas numpy

# Add with specific version
uv add "requests>=2.28.0"

Development Dependencies

# Add development dependencies
uv add --dev pytest black ruff

# Add both regular and dev dependencies
uv add requests pytest --dev

Optional Dependencies

# Add package with extras
uv add "requests[security]"

# Add multiple extras
uv add "pandas[excel,postgresql]"

Removing Dependencies

Remove dependencies from your project:

# Remove a single dependency
uv remove requests

# Remove multiple dependencies
uv remove requests pandas

# Remove a development dependency
uv remove --dev pytest

Version Constraints

UV supports various version constraint formats:

# Exact version
uv add "requests==2.28.0"

# Minimum version
uv add "requests>=2.28.0"

# Version range
uv add "requests>=2.28.0,<3.0.0"

# Compatible release (equivalent to >=2.28.0,<3.0.0)
uv add "requests~=2.28.0"

Dependency Resolution

UV automatically resolves dependencies when you add them:

# View dependency tree
uv tree

# Update dependencies
uv sync

# Update with upgrade
uv sync --upgrade

Resolution Features

  1. Lockfile Generation:
# Generate/update lockfile
uv lock

# Show outdated dependencies
uv lock --check
  1. Platform-Specific Resolution:
# Resolve for specific platform
uv lock --platform win32 --platform linux

# Include all platforms
uv lock --all-platforms

Managing Dependencies in pyproject.toml

UV uses pyproject.toml for dependency management:

[project]
name = "myproject"
version = "0.1.0"
dependencies = [
    "requests>=2.28.0",
    "pandas~=2.0.0"
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0.0",
    "black",
    "ruff"
]

Advanced Features

Direct URLs

Install from URLs or Git repositories:

# Install from Git
uv add "git+https://github.com/user/repo.git"

# Install from specific branch
uv add "git+https://github.com/user/repo.git@branch"

Local Dependencies

Install from local paths:

# Install local package
uv add "./local-package"

# Install in editable mode
uv add -e "./local-package"

Dependency Groups

Create custom dependency groups:

[project.optional-dependencies]
test = ["pytest>=7.0.0"]
lint = ["black", "ruff"]
docs = ["sphinx"]
# Install specific groups
uv add --optional "test,lint"

Best Practices

  1. Use Lockfiles
    • Always commit your lockfile
    • Run uv lock after dependency changes
    • Use uv sync to install from lockfile
  2. Version Constraints
    • Use >= for minimum versions
    • Use ~= for compatible releases
    • Avoid * or leaving versions unspecified
  3. Development Dependencies
    • Keep dev dependencies separate
    • Use appropriate groups for different purposes
    • Document dev setup requirements
  4. Regular Updates
    • Regularly check for updates
    • Review dependency tree for conflicts
    • Keep lockfile up to date

Troubleshooting

Common dependency issues and solutions:

  1. Version Conflicts
# View detailed dependency tree
uv tree --depth 999

# Try upgrading all dependencies
uv sync --upgrade
  1. Resolution Failures
# Try with verbose output
uv -v add package-name

# Clear cache and retry
uv cache clean
uv add package-name
  1. Lockfile Issues
# Regenerate lockfile
uv lock --regenerate

# Force update
uv sync --force

For more information about dependency management, use:

uv help add
uv help remove
uv help sync

Virtual Environments with UV

UV provides robust virtual environment management capabilities, allowing you to create isolated Python environments for your projects. This guide covers everything you need to know about working with virtual environments in UV.

Creating Virtual Environments

UV makes it easy to create new virtual environments:

# Create a virtual environment in the current directory
uv venv

# Create with specific name
uv venv myenv

# Create with specific Python version
uv venv --python 3.11

Location Options

# Create in specific directory
uv venv /path/to/env

# Create in project directory
uv venv .venv

Managing Environments

UV provides several commands for managing virtual environments:

Creating with Specific Settings

# Force creation (replace existing)
uv venv --force

# Create with prompt name
uv venv --prompt myproject

Working with Requirements

# Install dependencies after creation
uv pip install -r requirements.txt

# Sync with project dependencies
uv sync

Environment Isolation

UV ensures proper isolation between environments:

  1. Package Isolation: Each environment has its own packages
  2. Python Version Isolation: Can use different Python versions
  3. System Isolation: Independent from system Python packages

Best Practices for Isolation

  • Create separate environments for different projects
  • Use project-specific Python versions
  • Maintain clear dependency boundaries
  • Document environment requirements

Activation and Deactivation

Activation

On Unix-like systems (Linux/macOS):

source .venv/bin/activate

On Windows:

.venv\Scripts\activate

Deactivation

From any platform:

deactivate

Working with Environments

Running Commands

# Run command in environment without activation
uv run python script.py

# Run with specific Python version
uv run --python 3.11 pytest

# Run multiple commands
uv run pytest black ruff

Managing Packages

# Install packages in active environment
uv pip install requests

# Install in specific environment
uv pip install --venv /path/to/env requests

Best Practices

  1. Environment Per Project
    • Create separate environments for each project
    • Use consistent naming (e.g., .venv)
    • Document environment setup steps
  2. Version Control
    • Add .venv to .gitignore
    • Include requirements files or lockfiles
    • Document Python version requirements
  3. Environment Management
    • Regularly update dependencies
    • Clean unused environments
    • Keep environments focused (avoid installing unnecessary packages)
  4. Reproducibility
    • Use lockfiles for deterministic installs
    • Document all dependencies
    • Specify exact Python versions

Common Workflows

Project Setup

# Create new project
uv init myproject
cd myproject

# Create environment
uv venv

# Add dependencies
uv add requests pytest --dev

# Activate environment
source .venv/bin/activate  # Unix
# .venv\Scripts\activate  # Windows

Development Workflow

# Activate environment
source .venv/bin/activate

# Install dependencies
uv sync

# Run tests
uv run pytest

# Deactivate when done
deactivate

Troubleshooting

Common issues and solutions:

  1. Environment Creation Fails
# Try with verbose output
uv -v venv

# Force recreation
uv venv --force
  1. Activation Issues
  • Ensure correct activation script for your shell
  • Check environment path exists
  • Verify Python version compatibility
  1. Package Installation Problems
# Clear cache and retry
uv cache clean
uv pip install package-name

# Check for conflicts
uv pip freeze

For more information about virtual environments, use:

uv help venv

Running Projects with UV

UV provides flexible ways to run Python scripts and commands in your project environments. This guide covers everything you need to know about executing Python code with UV.

Executing Python Scripts

UV makes it easy to run Python scripts with proper environment isolation:

# Run a simple script
uv run script.py

# Run with arguments
uv run script.py --arg1 value1

# Run multiple scripts
uv run script1.py script2.py

Script Dependencies

UV supports inline dependency declarations in scripts:

# example.py
import requests  # @uv-dependency requests>=2.31.0
import pandas as pd  # @uv-dependency pandas>=2.0.0

response = requests.get("https://api.example.com")
df = pd.DataFrame(response.json())

Run scripts with dependencies:

uv run example.py  # UV will automatically handle dependencies

Running Commands in Virtual Environments

UV can run any command in your project's virtual environment:

# Run Python interpreter
uv run python

# Run project tools
uv run pytest
uv run black .
uv run ruff check

# Run multiple commands
uv run black . ruff check pytest

Environment Options

# Run in specific virtual environment
uv run --venv /path/to/env pytest

# Run without creating virtual environment
uv run --no-venv python script.py

Working with Different Python Versions

UV allows running scripts with specific Python versions:

# Run with specific Python version
uv run --python 3.11 script.py

# Run with PyPy
uv run --python pypy@3.8 script.py

# Run with exact version
uv run --python 3.11.4 script.py

Project Scripts

Define common commands in pyproject.toml:

[tool.uv.scripts]
test = "pytest"
lint = "ruff check && black --check ."
format = "black . && ruff check --fix"

Run defined scripts:

uv run test
uv run lint
uv run format

Advanced Features

Environment Variables

# Set environment variables
UV_PYTHON_PATH=/custom/path uv run script.py

# Use .env file
uv run --env-file .env script.py

Working Directory

# Run from specific directory
uv run --directory /path/to/dir script.py

# Run in project root
uv run --project /path/to/project script.py

Output Control

# Quiet mode
uv run -q script.py

# Verbose output
uv run -v script.py

# No progress bars
uv run --no-progress script.py

Best Practices

  1. Script Dependencies
    • Use inline dependencies for standalone scripts
    • Keep dependencies minimal and specific
    • Document dependency requirements
  2. Environment Management
    • Create dedicated environments for different purposes
    • Use appropriate Python versions
    • Keep environments clean and focused
  3. Project Organization
    • Define common commands in pyproject.toml
    • Use consistent naming for scripts
    • Document required environment setup
  4. Version Control
    • Include script dependencies in version control
    • Document Python version requirements
    • Share common script definitions

Common Workflows

Development Workflow

# Run tests
uv run pytest

# Format code
uv run black .

# Lint code
uv run ruff check

# Start development server
uv run flask run --debug

Deployment Workflow

# Run with production settings
UV_ENV=production uv run gunicorn app:app

# Run database migrations
uv run alembic upgrade head

Troubleshooting

Common issues and solutions:

  1. Script Not Found
  • Check file path
  • Verify script permissions
  • Ensure correct working directory
  1. Dependency Issues
# Clear cache and retry
uv cache clean
uv run script.py

# Check dependency resolution
uv tree
  1. Python Version Problems
# List available versions
uv python list

# Install required version
uv python install 3.11

For more information about running projects, use:

uv help run

Project Structure with UV

UV provides a standardized way to structure Python projects, making them easy to maintain and share. This guide covers how to organize and configure your UV projects effectively.

Project Initialization

Create a new project with UV:

# Create basic project
uv init myproject

# Create and enter project directory
cd myproject

Directory Structure

A typical UV project has the following structure:

myproject/
├── .venv/                 # Virtual environment directory
├── .python-version        # Python version specification
├── pyproject.toml        # Project configuration
├── src/                  # Source code directory
│   └── myproject/       # Main package directory
│       ├── __init__.py
│       └── main.py
├── tests/               # Test directory
│   ├── __init__.py
│   └── test_main.py
└── README.md           # Project documentation

Project Configuration

UV uses pyproject.toml for project configuration:

[project]
name = "myproject"
version = "0.1.0"
description = "My project description"
authors = [
    { name = "Your Name", email = "you@example.com" }
]
dependencies = [
    "requests>=2.28.0",
    "pandas~=2.0.0"
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0.0",
    "black",
    "ruff"
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.uv.scripts]
test = "pytest"
lint = "ruff check && black --check ."
format = "black . && ruff check --fix"

Best Practices

Source Code Organization

  1. Use src Layout:
    • Place package code under src/
    • Ensures clean installation testing
    • Prevents import confusion
  2. Package Naming:
    • Use clear, unique package names
    • Follow Python naming conventions
    • Avoid common package names

Configuration Management

  1. Environment Management:
    • Use .python-version for Python version
    • Keep virtual environment in .venv
    • Document environment setup

Version Control:

# .gitignore
.venv/
__pycache__/
*.pyc
dist/
*.egg-info/

Development Setup

Scripts Configuration:

[tool.uv.scripts]
test = "pytest"
coverage = "pytest --cov"
format = "black ."
typecheck = "mypy src"

Developer Tools:

[project.optional-dependencies]
dev = [
    "pytest",
    "black",
    "ruff",
    "mypy"
]

Common Project Types

Library Project

[project]
name = "mylibrary"
version = "0.1.0"
description = "A Python library"
requires-python = ">=3.8"

[project.urls]
Homepage = "https://github.com/username/mylibrary"
Documentation = "https://mylibrary.readthedocs.io"

Application Project

[project]
name = "myapp"
version = "0.1.0"
description = "A Python application"

[project.scripts]
myapp = "myapp.cli:main"

[tool.uv.scripts]
start = "python -m myapp"

Working with Projects

Development Workflow

# Set up development environment
uv venv
uv add --dev ".[dev]"

# Run tests
uv run test

# Format code
uv run format

# Build project
uv build

Dependency Management

# Add dependencies
uv add requests pandas

# Add development dependencies
uv add --dev pytest black

# Update dependencies
uv sync --upgrade

Advanced Configuration

Multiple Python Versions

[project]
requires-python = ">=3.8,<4.0"

Package Data

[tool.hatch.build.targets.wheel]
packages = ["src/myproject"]

[tool.hatch.build.targets.sdist]
include = [
    "src/myproject",
    "tests",
    "README.md"
]

Development Tools Configuration

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]

[tool.ruff]
select = ["E", "F", "B"]
ignore = ["E501"]

[tool.black]
line-length = 88

Troubleshooting

Common project issues and solutions:

  1. Import Issues
  • Check src directory structure
  • Verify package installation
  • Check Python path
  1. Build Problems
# Clean build artifacts
rm -rf dist/ build/ *.egg-info/

# Rebuild
uv build
  1. Configuration Issues
  • Validate TOML syntax
  • Check indentation
  • Verify dependencies exist

For more information about project structure, use:

uv help init

Lockfile Management with UV

UV uses lockfiles to ensure reproducible installations across different environments. This guide covers everything you need to know about working with lockfiles in UV.

Understanding Lockfiles

UV's lockfile system provides:

  • Reproducible builds
  • Deterministic dependency resolution
  • Platform-specific dependency handling
  • Hash verification for security

Basic Lockfile Operations

Generating Lockfiles

# Generate or update lockfile
uv lock

# Generate with specific platforms
uv lock --platform win32 --platform linux

# Include all platforms
uv lock --all-platforms

Using Lockfiles

# Install from lockfile
uv sync

# Update dependencies while respecting lockfile
uv sync --upgrade

# Check if lockfile is up to date
uv lock --check

Lockfile Structure

UV's lockfile includes:

  • Exact package versions
  • Dependency relationships
  • Platform-specific requirements
  • Package hashes
  • Metadata

Example lockfile structure:

# requirements.lock
[[package]]
name = "requests"
version = "2.31.0"
dependencies = [
    "certifi>=2017.4.17",
    "charset-normalizer>=2,<4",
    "idna>=2.5,<4",
    "urllib3>=1.21.1,<3"
]
summary = "Python HTTP for Humans."

[[package]]
name = "urllib3"
version = "2.0.7"
dependencies = []
summary = "HTTP library with thread-safe connection pooling, file post, and more."

Advanced Features

Platform-Specific Resolution

# Resolve for specific Python version
uv lock --python-version 3.11

# Resolve for specific architecture
uv lock --platform-release linux-x86_64

Hash Verification

# Generate with hashes
uv lock --generate-hashes

# Verify hashes during sync
uv sync --verify

Export Options

# Export to requirements.txt
uv export requirements.txt

# Export with hashes
uv export --generate-hashes requirements.txt

# Export development dependencies
uv export --dev requirements-dev.txt

Best Practices

  1. Version Control
    • Always commit lockfiles
    • Update lockfiles deliberately
    • Document lockfile update process
  2. Platform Handling
    • Include relevant platforms
    • Test on all target platforms
    • Document platform requirements
  3. Update Strategy
    • Regular scheduled updates
    • Security update process
    • Testing after updates
  4. Dependency Groups
# Update specific groups
uv lock --group dev --group test

# Export group-specific lockfiles
uv export --group dev requirements-dev.txt

Common Workflows

Initial Setup

# Create new project
uv init myproject
cd myproject

# Add dependencies
uv add requests pandas

# Generate lockfile
uv lock

Update Process

# Check for updates
uv lock --check

# Update dependencies
uv lock --upgrade

# Sync environment
uv sync

CI/CD Integration

# CI installation
uv sync

# Verify lockfile
uv lock --check

# Platform-specific checks
uv lock --platform linux-x86_64 --check

Troubleshooting

Common lockfile issues and solutions:

  1. Resolution Conflicts
# View dependency tree
uv tree

# Force regenerate lockfile
uv lock --force
  1. Platform Issues
# Clear platform-specific entries
uv lock --platform current

# Regenerate for all platforms
uv lock --all-platforms
  1. Hash Mismatches
# Regenerate hashes
uv lock --generate-hashes

# Force sync with new hashes
uv sync --force

Working with Multiple Python Versions

# Generate for multiple Python versions
uv lock --python-version 3.8 --python-version 3.9

# Check compatibility
uv lock --check --python-version 3.8

Maintenance Tasks

Regular maintenance activities:

  1. Update Check
# Check for updates
uv lock --check
  1. Security Updates
# Update with security fixes
uv lock --upgrade-package requests
  1. Clean Up
# Remove unused dependencies
uv lock --prune

For more information about lockfile management, use:

uv help lock
uv help sync
uv help export

Building and Publishing with UV

UV provides tools for building Python packages and publishing them to package indexes like PyPI. This guide covers the complete process of building and publishing packages with UV.

Building Packages

Basic Build

# Build package
uv build

# Build in specific directory
uv build --directory path/to/project

# Build with output directory
uv build --outdir dist/

Build Configurations

Configure build settings in pyproject.toml:

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "myproject"
version = "0.1.0"
description = "My project description"
readme = "README.md"
requires-python = ">=3.8"

Build Options

# Build specific formats
uv build --sdist  # Source distribution only
uv build --wheel  # Wheel distribution only

# Build with specific Python version
uv build --python 3.11

Publishing Packages

Basic Publishing

# Publish to PyPI
uv publish

# Publish to test PyPI
uv publish --repository testpypi

Authentication

# Using token
UV_PYPI_TOKEN=your-token uv publish

# Using credentials file
uv publish --credentials-file ~/.pypirc

Publishing Options

# Skip existing versions
uv publish --skip-existing

# Verify before publishing
uv publish --verify

# Sign distributions
uv publish --sign

Package Versioning

Version Management

[project]
version = "0.1.0"

Version Formats

  • Semantic Versioning: MAJOR.MINOR.PATCH
  • Alpha/Beta releases: 0.1.0a1, 0.1.0b1
  • Release candidates: 0.1.0rc1

Distribution Options

Source Distributions

Configure source distribution in pyproject.toml:

[tool.hatch.build.targets.sdist]
include = [
    "src/",
    "tests/",
    "README.md",
    "LICENSE"
]
exclude = [
    "*.pyc",
    "__pycache__",
    "*.so"
]

Wheel Distributions

Configure wheel distribution:

[tool.hatch.build.targets.wheel]
packages = ["src/mypackage"]

Best Practices

  1. Version Control
    • Tag releases in git
    • Use consistent version numbering
    • Document release process

Package Data

[tool.hatch.build.targets.wheel]
include-package-data = true

[tool.hatch.build.targets.wheel.sources]
"src" = "mypackage"

Documentation

[project]
readme = "README.md"
license = "MIT"

[project.urls]
Homepage = "https://github.com/username/project"
Documentation = "https://project.readthedocs.io"

Distribution Verification

# Build and verify locally
uv build
uv publish --verify --dry-run

Common Workflows

Release Process

# 1. Update version in pyproject.toml
# 2. Build distributions
uv build

# 3. Verify distributions
uv publish --verify --dry-run

# 4. Publish to TestPyPI
uv publish --repository testpypi

# 5. Test installation from TestPyPI
uv pip install --index-url https://test.pypi.org/simple/ mypackage

# 6. Publish to PyPI
uv publish

CI/CD Integration

# Example GitHub Actions workflow
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Build and publish
        env:
          UV_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
        run: |
          uv build
          uv publish

Troubleshooting

Common build and publish issues:

  1. Build Errors
# Clean previous builds
rm -rf dist/ build/ *.egg-info/

# Build with verbose output
uv -v build
  1. Publishing Issues
# Test authentication
uv publish --dry-run

# Check package validity
uv publish --verify
  1. Version Conflicts
# Check existing versions
uv publish --skip-existing

# Force update
uv publish --force

Repository Configuration

Configure multiple repositories in .pypirc:

[distutils]
index-servers =
    pypi
    testpypi

[pypi]
repository = https://upload.pypi.org/legacy/
username = __token__
password = your-token

[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = your-test-token

For more information about building and publishing, use:

uv help build
uv help publish

Tool Management with UV

UV provides powerful capabilities for managing Python command-line tools, similar to pipx. This guide covers how to install, run, and manage Python tools effectively with UV.

Quick Tool Execution

Use uvx (alias for uv tool run) to run tools without installation:

# Run a tool directly
uvx black .
uvx ruff check

# Run with specific version
uvx "black==23.12.1" .

# Run with arguments
uvx pycowsay "Hello, World!"

Installing Tools

Global Installation

# Install a tool globally
uv tool install black

# Install specific version
uv tool install "ruff==0.1.9"

# Install multiple tools
uv tool install black ruff mypy

Installation Options

# Install with extras
uv tool install "sphinx[docs]"

# Install from git
uv tool install "git+https://github.com/user/repo.git"

# Install in specific directory
uv tool install --root /path/to/dir black

Managing Tools

Listing Tools

# List installed tools
uv tool list

# Show detailed information
uv tool list --verbose

Updating Tools

# Update specific tool
uv tool install --upgrade black

# Update all tools
uv tool install --upgrade $(uv tool list)

Uninstalling Tools

# Remove a tool
uv tool uninstall black

# Remove multiple tools
uv tool uninstall black ruff

Tool Environments

UV creates isolated environments for each tool:

# View tool directory
uv tool dir

# Update shell for tool access
uv tool update-shell

Environment Structure

~/.uv/tools/
├── black/
│   ├── bin/
│   └── venv/
├── ruff/
│   ├── bin/
│   └── venv/
└── mypy/
    ├── bin/
    └── venv/

Best Practices

  1. Tool Isolation
    • Install tools globally using uv tool install
    • Use uvx for one-time tool execution
    • Keep project-specific tools in project dependencies
  2. Version Management
    • Specify versions for reproducibility
    • Update tools regularly
    • Monitor for security updates
  3. Performance
    • Use uvx for occasional use
    • Install globally for frequent use
    • Clean unused tools regularly

Shell Integration

# Add to shell configuration
eval "$(uv tool update-shell)"

Common Workflows

Development Setup

# Install common development tools
uv tool install black ruff mypy pytest

# Update shell path
uv tool update-shell

Tool Usage

# Format code
black .

# Run linter
ruff check

# Type checking
mypy .

Maintenance

# List installed tools
uv tool list

# Update all tools
uv tool install --upgrade $(uv tool list)

# Clean unused tools
uv tool uninstall unused-tool

Advanced Features

Custom Installation Location

# Install in custom location
UV_TOOLS_PATH=/custom/path uv tool install black

Tool Dependencies

# Install tool with specific Python version
uv tool install --python 3.11 black

# Install with platform-specific dependencies
uv tool install --platform win32 black

Multiple Versions

# Install specific version alongside existing
uv tool install "black==22.3.0" --suffix old

Troubleshooting

Common tool management issues:

  1. Installation Failures
# Try with verbose output
uv -v tool install package-name

# Clear cache and retry
uv cache clean
uv tool install package-name
  1. Path Issues
# Update shell path
uv tool update-shell

# Verify tool location
uv tool dir
  1. Version Conflicts
# Install specific version
uv tool install "package==version"

# Force reinstall
uv tool install --force package

Environment Variables

Important environment variables for tool management:

  • UV_TOOLS_PATH: Custom location for tool installations
  • UV_CACHE_DIR: Custom cache directory
  • UV_NO_CACHE: Disable cache usage

For more information about tool management, use:

uv help tool
uv help tool install
uv help tool uninstall
uv help tool list

Comparing with pipx

UV's tool management provides similar functionality to pipx:

Feature UV Command pipx Command
Run without installing uvx tool pipx run tool
Install globally uv tool install pipx install
List tools uv tool list pipx list
Uninstall tool uv tool uninstall pipx uninstall

The main advantages of UV's tool management:

  1. Faster installation and execution
  2. Integrated with other UV features
  3. Better cache management
  4. Cross-platform consistency

Cache Management with UV

UV uses a sophisticated caching system to improve performance and reduce disk usage. This guide covers how to effectively manage UV's cache system.

Understanding UV's Cache

UV maintains a global cache for:

  • Downloaded packages
  • Built wheels
  • Python installations
  • Tool environments

Cache Location

# View cache directory
uv cache dir

# Default locations:
# Linux: ~/.cache/uv
# macOS: ~/Library/Caches/uv
# Windows: %LOCALAPPDATA%\uv\Cache

Basic Cache Operations

Viewing Cache Information

# Show cache directory
uv cache dir

# Show cache size
du -sh $(uv cache dir)

Cleaning Cache

# Remove all cache entries
uv cache clean

# Remove outdated entries
uv cache prune

Cache Configuration

Environment Variables

# Set custom cache directory
export UV_CACHE_DIR=/path/to/cache

# Disable cache
export UV_NO_CACHE=1

Command-line Options

# Run commands without cache
uv --no-cache install requests

# Use specific cache directory
uv --cache-dir /path/to/cache install requests

Cache Components

UV's cache consists of several components:

  1. Package Cache
    • Downloaded package archives
    • Built wheels
    • Package metadata
  2. Python Cache
    • Installed Python versions
    • Python build artifacts
    • Installation metadata
  3. Tool Cache
    • Installed tool environments
    • Tool metadata
    • Tool binaries

Cache Management Strategies

Regular Maintenance

# Weekly maintenance routine
uv cache prune        # Remove outdated entries
uv cache clean --old  # Clean old entries

Space Optimization

# Remove specific package versions
uv cache clean package-name==1.0.0

# Clean old Python versions
uv python uninstall 3.8

Cache Policies

Best practices for cache management:

  1. Regular Cleaning
    • Run uv cache prune monthly
    • Clean unused packages quarterly
    • Review Python versions annually
  2. Space Management
    • Monitor cache size
    • Set cache size limits
    • Clean when space is low
  3. CI/CD Considerations
    • Use cache in CI for speed
    • Clean cache in CI regularly
    • Set appropriate cache paths

Advanced Cache Features

Selective Cache Operations

# Clean specific cache types
uv cache clean --packages
uv cache clean --tools
uv cache clean --python

# Clean by age
uv cache clean --older-than 30d

Cache Verification

# Verify cache integrity
uv cache verify

# Rebuild corrupted entries
uv cache rebuild

Troubleshooting

Common cache issues and solutions:

  1. Cache Corruption
# Clear corrupted cache
uv cache clean --force

# Rebuild cache
uv cache rebuild
  1. Space Issues
# Find large cache entries
uv cache list --size

# Clean old entries
uv cache clean --old
  1. Permission Problems
# Fix cache permissions
chmod -R u+rw $(uv cache dir)

CI/CD Integration

Example cache configuration for CI/CD:

# GitHub Actions example
jobs:
  build:
    steps:
      - uses: actions/cache@v2
        with:
          path: |
            ~/.cache/uv
          key: ${{ runner.os }}-uv-${{ hashFiles('**/requirements.txt') }}
# GitLab CI example
cache:
  paths:
    - ~/.cache/uv/
  key: ${CI_COMMIT_REF_SLUG}

Best Practices

  1. Regular Maintenance
    • Schedule regular cache cleaning
    • Monitor cache size
    • Keep cache organized
  2. Performance Optimization
    • Use cache for frequent operations
    • Clean unnecessary cache entries
    • Configure appropriate cache size
  3. Security Considerations
    • Verify package hashes
    • Clean sensitive data
    • Manage permissions properly

Environment Variables Summary

Variable Purpose Example
UV_CACHE_DIR Set cache location /path/to/cache
UV_NO_CACHE Disable cache 1
UV_CACHE_MAX_SIZE Set cache size limit 10G

For more information about cache management, use:

uv help cache
uv help cache clean
uv help cache prune

CI/CD Integration with UV

This guide covers how to effectively integrate UV into your CI/CD pipelines, ensuring reliable and efficient Python package management in your automation workflows.

Basic CI/CD Setup

GitHub Actions Example

name: Python CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11"]

    steps:
      - uses: actions/checkout@v3

      # Install UV
      - name: Install UV
        run: |
          curl -LsSf https://astral.sh/uv/install.sh | sh

      # Setup Python
      - name: Setup Python ${{ matrix.python-version }}
        run: |
          uv python install ${{ matrix.python-version }}
          uv python pin ${{ matrix.python-version }}

      # Install dependencies
      - name: Install dependencies
        run: |
          uv venv
          uv pip sync requirements.txt
          uv pip sync requirements-dev.txt

      # Run tests
      - name: Run tests
        run: |
          uv run pytest

GitLab CI Example

image: python:3.11

variables:
  UV_CACHE_DIR: .uv-cache

cache:
  paths:
    - .uv-cache/
    - .venv/

stages:
  - test
  - build
  - deploy

test:
  stage: test
  script:
    - curl -LsSf https://astral.sh/uv/install.sh | sh
    - uv venv
    - uv pip sync requirements.txt
    - uv run pytest

build:
  stage: build
  script:
    - uv build
  artifacts:
    paths:
      - dist/

Automation Strategies

Dependency Management

  1. Using Lockfiles
- name: Verify lockfile
  run: uv lock --check

- name: Install dependencies
  run: uv sync
  1. Multiple Python Versions
- name: Setup Python environments
  run: |
    uv python install ${{ matrix.python-version }}
    uv venv
    uv sync

Build and Publish

name: Publish Package

on:
  release:
    types: [created]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Install UV
        run: curl -LsSf https://astral.sh/uv/install.sh | sh

      - name: Build and publish
        env:
          UV_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
        run: |
          uv build
          uv publish

Best Practices

1. Cache Management

- name: Cache UV dependencies
  uses: actions/cache@v3
  with:
    path: |
      ~/.cache/uv
      .venv
    key: ${{ runner.os }}-uv-${{ hashFiles('**/requirements.txt') }}
    restore-keys: |
      ${{ runner.os }}-uv-

2. Environment Variables

env:
  UV_NO_PROGRESS: 1
  UV_SYSTEM_PYTHON: 0
  UV_CACHE_DIR: .uv-cache
  UV_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}

3. Error Handling

- name: Install dependencies
  run: |
    uv venv || (rm -rf .venv && uv venv)
    uv sync || (uv cache clean && uv sync)
  continue-on-error: false

Common Workflows

1. Testing Workflow

test:
  steps:
    - name: Run linting
      run: |
        uv run ruff check .
        uv run black --check .

    - name: Run type checking
      run: uv run mypy .

    - name: Run tests
      run: uv run pytest --cov

2. Build and Release Workflow

release:
  steps:
    - name: Build package
      run: uv build

    - name: Test build
      run: |
        uv venv test-env
        uv pip install dist/*.whl
        uv run pytest

    - name: Publish
      run: uv publish

Troubleshooting

Common Issues and Solutions

  1. Cache Issues
- name: Clean cache
  if: failure()
  run: |
    uv cache clean
    uv sync
  1. Permission Problems
- name: Fix permissions
  run: |
    chmod -R 755 .uv-cache
    chmod -R 755 .venv
  1. Network Issues
- name: Install with retry
  run: |
    for i in 1 2 3; do
      uv sync && break || sleep 15;
    done

Platform-Specific Considerations

Windows

windows:
  runs-on: windows-latest
  steps:
    - name: Install UV
      run: |
        powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
        uv --version

macOS

macos:
  runs-on: macos-latest
  steps:
    - name: Install UV
      run: |
        curl -LsSf https://astral.sh/uv/install.sh | sh
        uv --version

Security Best Practices

  1. Secret Management
env:
  UV_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
  1. Hash Verification
- name: Verify dependencies
  run: uv sync --verify
  1. Artifact Signing
- name: Sign distributions
  run: |
    uv build
    uv publish --sign

For more information about CI/CD integration, use:

uv help
uv help publish

Migrating from pip to UV

This guide will help you transition from pip to UV, showing equivalent commands and helping you adapt your existing workflows.

Command Equivalents

Basic Package Management

pip Command UV Command Notes
pip install package uv pip install package Direct equivalent
pip install -r requirements.txt uv pip sync requirements.txt More reproducible
pip uninstall package uv pip uninstall package Direct equivalent
pip list uv pip list List installed packages
pip freeze uv pip freeze Generate requirements

Virtual Environments

pip/venv Command UV Command Notes
python -m venv .venv uv venv Create virtual environment
pip install -e . uv pip install -e . Install in editable mode

Converting Requirements Files

Basic Requirements

# Convert existing requirements.txt to UV format
uv pip compile requirements.in -o requirements.txt

# Generate requirements with hashes
uv pip compile --generate-hashes requirements.in

Development Requirements

# Convert dev requirements
uv pip compile requirements-dev.in -o requirements-dev.txt

# Include constraints
uv pip compile --constraint requirements.txt requirements-dev.in

Adapting Common Workflows

Project Setup

From:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

To:

uv venv
source .venv/bin/activate
uv pip sync requirements.txt

Development Installation

From:

pip install -e ".[dev]"

To:

uv pip install -e ".[dev]"
# or
uv add --dev ".[dev]"

Requirements Generation

From:

pip freeze > requirements.txt

To:

uv pip compile requirements.in
# or for direct freeze
uv pip freeze > requirements.txt

Best Practices

1. Use Lockfiles

Instead of:

pip freeze > requirements.txt

Use:

# Create requirements.in
uv pip compile requirements.in -o requirements.txt
# Install from lockfile
uv pip sync requirements.txt

2. Handle Dev Dependencies

Instead of:

pip install -r requirements-dev.txt

Use:

uv add --dev pytest black ruff
uv pip sync requirements-dev.txt

3. Virtual Environments

Instead of:

python -m venv .venv
pip install -r requirements.txt

Use:

uv venv
uv sync

Common Challenges

1. Dependencies Resolution

pip:

pip install --no-deps package
pip check

UV:

uv pip install --no-deps package
uv pip check

2. Editable Installs

pip:

pip install -e .

UV:

uv add -e .
# or
uv pip install -e .

3. Version Specifiers

pip:

pip install "package>=1.0.0"

UV:

uv add "package>=1.0.0"
# or
uv pip install "package>=1.0.0"

CI/CD Migration

GitHub Actions

From:

- uses: actions/setup-python@v4
- run: |
    python -m pip install -r requirements.txt

To:

- name: Install UV
  run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Install dependencies
  run: |
    uv venv
    uv sync

Requirements Caching

From:

- uses: actions/cache@v3
  with:
    path: ~/.cache/pip
    key: pip-${{ hashFiles('requirements.txt') }}

To:

- uses: actions/cache@v3
  with:
    path: ~/.cache/uv
    key: uv-${{ hashFiles('requirements.txt') }}

Troubleshooting

1. Package Not Found

If you encounter package not found errors:

# Clear UV cache
uv cache clean

# Try installing with different index
uv pip install --index-url https://pypi.org/simple package

2. Version Conflicts

# View dependency tree
uv pip tree

# Force reinstall
uv pip install --force-reinstall package

3. Cache Issues

# Clean cache
uv cache clean

# Retry installation
uv pip sync requirements.txt

Migration Checklist

  1. [ ] Install UV
  2. [ ] Convert requirements files
  3. [ ] Update CI/CD configurations
  4. [ ] Update development documentation
  5. [ ] Test all development workflows
  6. [ ] Update build scripts
  7. [ ] Train team members

For more information about pip compatibility, use:

uv help pip