Skip to content

Python uv cheat sheet#

Python uv common usage cheat sheet, but doesn't cover all the features.

Init project#

uv init can have 3 templates: --app (by default), --lib and --package.

CommandDescription
uv init my-project -p python3.13Init new project with new folder
uv init -p python3.13Init an existing project with python3.13
uv init --libLibraries template creates a src folder whereas application template only creates a main.py file
uv init --packageInit a project with package template, same as libraries but pyproject.toml has a [project.scripts] key, so this is for command-line interface you can later run the command by: uv run pkg-1
pyproject.toml created by uv init --package pkg-1
[project.scripts]
pkg-1 = "pkg_1:main"

uv init under a folder with already a pyproject.toml

If upper folders has already a pyproject.toml file, uv will also add the new project (created by uv init) as [tool.uv.workspace] members. This cheat sheet doesn't cover that. As that makes uv workspace management more complex. You might need to use uv sync --active to install dependencies in the separate venv of the sub module if needed.

Add dependencies#

optional-dependencies vs dependency-groups#

Ref:

optional-dependencies are part of the published metadata for your package, while dependency-groups are only visible when working with your package locally

Add to project.dependencies as main dependencies#

uv add fastapi

Could be installed by end users with uv pip install temp

pyproject.toml
[project]
name = "temp"
...
dependencies = [
    "fastapi>=0.116.1",
]

Add to project.optional-dependencies as extra packages#

uv add aiohttp --optional aio

Could be installed by end users with uv pip install temp[aio]

pyproject.toml
[project]
name = "temp"
...
[project.optional-dependencies]
aio = [
    "aiohttp>=3.12.15",
]

Add to dependency-groups for local development#

uv add ruff --dev
# or
uv add ruff --group dev

uv add ty --group typing

Dependencies declared in the dependency-groups part are not added to the package metadata, so end users cannot install them directly.

pyproject.toml
[project]
name = "temp"
...
[dependency-groups]
dev = [
    "ruff>=0.12.4",
]
typing = [
    "ty>=0.0.1a19",
]

Add to dependency sources#

Dependency sources are for local development only.

uv add git+https://github.com/encode/httpx
uv add --editable ../temp1/lib_1
[project]
name = "temp"
...
[tool.uv.sources]
httpx = { git = "https://github.com/encode/httpx" }
lib-1 = { path = "../temp1/lib_1", editable = true }

Note

For multiple packages in the same repository, workspaces may be a better fit.

Declare conflicting dependencies#

uv supports explicit declaration of conflicting dependency groups. For example, to declare that the optional-dependency groups extra1 and extra2 are incompatible:

pyproject.toml
[tool.uv]
conflicts = [
    [
      { extra = "extra1" },
      { extra = "extra2" },
    ],
]

Or, to declare the development dependency groups group1 and group2 incompatible:

pyproject.toml
[tool.uv]
conflicts = [
    [
      { group = "group1" },
      { group = "group2" },
    ],
]

Install dependencies#

pyproject.toml
[project]
name = "temp"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "fastapi>=0.116.1",
]

# this is the optional extra part, useful for end user
[project.optional-dependencies]
aio = [
    "aiohttp>=3.12.15",
]

# this is the local development groups part, useful for developers
[dependency-groups]
dev = [
    "ruff>=0.12.4",
]
typing = [
    "ty>=0.0.1a19",
]
all = [
    {include-group = "dev"},
    {include-group = "typing"},
]

The --dev, --only-dev, and --no-dev flags are equivalent to --group dev, --only-group dev, and --no-group dev respectively.

without --no-dev, the dev group is already installed with uv sync

Use uv sync --no-dev or uv sync --no-default-groups to avoid installing the dev group. By default, uv includes the dev dependency group in the environment (e.g., during uv run or uv sync). The default groups to include can be changed using the tool.uv.default-groups setting.

use uv sync --dry-run to see what will be the changes

CommandDescription
uv sync --no-devInstall dependencies only (without any extra nor any group)
uv syncInstall dependencies and dev group, no extras, no other groups than dev
uv sync --all-groupsInstall dependencies and all groups (dependency-groups)
uv sync --all-extrasInstall dependencies and all extras (project.optional-dependencies) and dev group (dev group is by default)
uv sync --all-extras --all-groupsInstall dependencies and all extras and all groups
uv sync --extra aioInstall dependencies and extra aio and dev group
uv sync --extra aio --no-devInstall dependencies and extra aio but without dev group
uv sync --extra aio --inexactInstall dependencies and dev groups and retain already installed extraneous packages not declared in pyproject.toml
uv sync --locked --no-devEnsure install by respecting uv.lock (ensure uv.lock won't be changed after uv sync) and raise an error if lock file doesn't confirm with pyproject.toml.

In 🐳 Dockerfile (official uv Dockerfile example), we often use uv sync --locked --no-install-project --no-dev, see Using uv in Docker to understand the usage of each parameters.
$ uv sync --locked --no-dev
Resolved 21 packages in 33ms
The lockfile at `uv.lock` needs to be updated, but `--locked` was provided.
To update the lockfile, run `uv lock`.

--locked vs --frozen vs --no-sync#

official doc: https://docs.astral.sh/uv/concepts/projects/sync/#automatic-lock-and-sync

uv.lock file related:

  • --locked: If the lockfile is not up-to-date, uv will raise an error instead of updating the lockfile. --locked could be considered as --ensure-locked.
  • --frozen: Use the lockfile without checking if it is up-to-date, no error will be raised.

venv related:

  • --no-sync: Do not update the venv.

Dependencies tree#

CommandDescription
uv pip treeDisplay the installed packages in a tree format
uv treeUpdate uv.lock based on pyproject.toml and display tree based on uv.lock, no package installation will occur. uv tree displays better than uv pip tree
uv tree --frozenDon't update uv.lock, just display tree based on the current uv.lock
uv tree --lockedIf uv.lock is not updated, display a warning message. This command is not very useful

List outdated packages#

  • uv tree --outdated: display a list of outdated packages with their latest public versions, no matter what pyproject.toml declares.
  • uv lock --check: check if uv.lock is up-to-date with pyproject.toml.

Upgrade packages and uv.lock#

uv.lock filecan be updated by uv lock, uv sync, uv run, uv add, uv remove.

CommandDescription
uv lockUpdate the uv.lock file to match the current state of pyproject.toml
uv lock -UUpdate the uv.lock file and upgrade all packages to their latest compatible versions
uv syncSame as uv lock but also installs the dependencies
uv sync -USame as uv lock -U but also installs the dependencies

uv lock vs uv lock -U and uv sync vs uv sync -U

If latest version of fastapi is 0.116.1, and pyproject.toml declares fastapi>=0.115.1, and current uv.lock has fastapi==0.115.1. then:

  • uv lock: no effect, as 0.115.1 is still within the range of >=0.115.1.
  • uv lock -U: upgrade fastapi to 0.116.1.

Same logic applies to uv sync and uv sync -U, except for sync installing the dependencies too.

-U (--upgrade for all packages) or -P (--upgrade-package for a specific package) respect always the version constraints defined in pyproject.toml.

Integrations#

Check this doc for more information on integrations with other tools and platforms (Docker, Jupyter, Github Actions, Pre Commit, PyTorch FastAPI, etc.).

Build#

Build with rust, C, C++, CPython backend#

uv can also build with extension module by --build-backend flag to work with Rust and C, C++, CPython etc.

Build isolation#

uv build isolation is by default, but some packages need to build against the same version of some packages installed in the project environment. For example, flask-attn, deepspeed, cchardet, etc.

Comments