uv - package and project manager

Short tutorial on uv: https://earthly.dev/blog/python-uv/arrow-up-right


General

uv is a fast Python package and project manager written in Rust. uv is a single tool designed to be a high-speed replacement for multiple Python development tools. It integrates the functionalities of packages like piparrow-up-right, pip-tools, pipx, poetry, pyenv, and virtualenv into one command-line interface.

Key Features

  • Speed: 10-100x faster than pip

  • Lock files: uv.lock for reproducible installs

  • Universal: Works across projects and Python versions

  • No separate pip/venv/virtualenv: All-in-one tool

Configuration Files

  • pyproject.toml: Project metadata and dependencies

  • uv.lock: Locked dependencies (like package-lock.json)

  • .python-version: Pinned Python version

uvx is for running Python tools in isolated environments.

UVX as a Python tool (uvx)

  • Function: UVX is a command for the uv Python tool that lets you run other Python tools without installing them globally.

  • Process: When you run uvx <tool>, it automatically creates a temporary, isolated Python environment, installs the tool, runs it, and then cleans up the environment.

  • Benefit: This prevents polluting your system with temporary dependencies and avoids potential version conflicts.

  • Alias: uvx is a convenient alias for the uv tool run command.

Nice overview of commands: https://docs.astral.sh/uv/getting-started/features/#python-versionsarrow-up-right


Common Workflows

Start new project:

What does uv init command do for you?

Normal uv init command creates these files and directories:

  • .python-version is the file which contains the python version this project is configured to use.

    • Pins the Python version for the project

    • Used by uv to automatically use the right Python

    • Can be changed with uv python pin <version>

  • .git directory

  • .gitignore file

  • main.py Python file

  • pyproject.toml is the configuration file for your project

    • Project metadata and configuration

    • Dependencies go in the dependencies = [] array

    • Standard Python packaging file (PEP 621)

  • README.md

uv init --app is the equivalent of uv init and is the default option.

uv add command

  • adds dependencies to your project

  • creates a virtual environment with .venv directory

  • creates a uv.lock file with exact versions of added dependencies.

  • run source .venv/bin/activate after uv add

What does uv run do?

It runs tools in project environment

Issues:

  • ❌ Inconsistent versions across team members

  • ❌ Tool version might not match project needs

  • ❌ CI/CD might have different versions

  • ❌ Hard to reproduce issues

Benefits:

  • Reproducibility: Everyone uses same tool versions

  • Isolation: Tool dependencies don't conflict with project

  • Version control: Tool versions in pyproject.toml

  • CI/CD consistency: Same environment everywhere

Hence, no "works on my machine" problems.


What do uv pip commands do?

uv pip is a drop-in replacement for pip, but much faster (10-100x).

Basic Commands

Use when:

  • Working with legacy projects using requirements.txt

  • Need pip-compatible workflow

  • Installing packages in existing venv

  • One-off installations

Don't use when:

  • Starting new projects (use uv add instead)

  • You want lock files (use uv project commands)


What is a lock file?

A lock file (uv.lock) is a detailed snapshot of every single dependency with exact versions used in your project.

Installation

The Problem Lock Files Solve

Without lock file:

Everyone gets identical dependencies


Direct vs Transitive Dependencies

Direct dependencies (you explicitly added):

Transitive dependencies (pulled in automatically):

  • requests needs urllib3, certifi, charset-normalizer, idna

  • Lock file captures all of them


Lock File vs Requirements

File
Purpose
Audience

pyproject.toml

High-level requirements

Humans

uv.lock

Exact resolved versions

Machines

pyproject.toml:

uv.lock:


Updating Dependencies

Committing to Git


Best Practices for uv.lock files

DO:

  • Commit uv.lock to git

  • Use uv sync --frozen in CI/CD

  • Regularly update with uv lock --upgrade

  • Review lock file changes in PRs

DON'T:

  • Manually edit uv.lock

  • Delete lock file to "fix" issues

  • Use different lock files for dev/prod

  • Commit .venv/ directory

Real-world example

Developer A (Monday):

Developer B (Friday):

Without lock file, Developer B might get flask==3.1.0 and sqlalchemy==2.0.25, causing subtle bugs.

The lock file is your time machine for dependencies! 🔒


--frozen option in uv sync command for CI/CD scenarios

What --frozen Does

Behavior:

  1. ✅ Installs dependencies from uv.lock (exact versions)

  2. Refuses to update uv.lock

  3. Fails if lock file is out of sync with pyproject.toml

Scenario: Developer Forgot to Update Lock

In CI/CD:


Integrations


Setup UV environment variables

https://docs.astral.sh/uv/reference/environment/arrow-up-right


Authentication with UV

https://docs.astral.sh/uv/concepts/authentication/arrow-up-right


About caching


Last updated