Кладовочка

О разном, чтобы было под рукой онлайн

Шпаргалка по uv: пакетный менеджер Python на Rust

uv — сверхбыстрый пакетный менеджер и менеджер проектов Python, написанный на Rust компанией Astral. Один инструмент заменяет: pip, pip-tools, pipx, poetry, pyenv, twine, virtualenv. В 10–100 раз быстрее pip. Кроссплатформенный lockfile (uv.lock), встроенное управление Python-версиями, инструментами и публикацией пакетов.

Установка

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

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

# Альтернативные способы
pip install uv                     # через pip
brew install uv                    # macOS Homebrew
winget install --id=astral-sh.uv -e  # Windows WinGet
cargo install --git https://github.com/astral-sh/uv uv

# Docker
docker pull ghcr.io/astral-sh/uv

# Обновление
uv self update

# Автодополнение shell
echo 'eval "$(uv generate-shell-completion bash)"' >> ~/.bashrc
echo 'eval "$(uv generate-shell-completion zsh)"' >> ~/.zshrc
uv generate-shell-completion fish | source  # Fish

Управление проектами

Создание проекта

# Новый проект в новой папке
uv init myproject

# Инициализация в текущей папке
uv init

# Типы проектов
uv init --app              # приложение (по умолчанию) — исполняемый код
uv init --lib              # библиотека — импортируемый код
uv init --package          # пакетируемый (для публикации в PyPI)

# С конкретной версией Python
uv init --python 3.12

# Скрипт (один файл с встроенными зависимостями)
uv init --script script.py
uv init --script script.py --python 3.11

Структура созданного проекта:

myproject/
  .git/
  .gitignore
  .python-version          # целевая версия Python
  .venv/                   # виртуальное окружение (после первого uv run/sync)
  README.md
  main.py                  # "Hello from myproject!"
  pyproject.toml           # метаданные + зависимости
  uv.lock                  # lockfile (после первого uv run/sync)

pyproject.toml — основа проекта

Файл pyproject.toml — главный конфигурационный файл Python-проекта. Здесь описано: как называется проект, какие библиотеки нужны, откуда их брать и как uv должен ими управлять. Ниже — все часто используемые секции с пояснениями «для чего» и «когда нужно».

[project] — имя, версия, зависимости

Что делает: базовая информация о проекте. Обязательная секция. Здесь указывается название, версия, минимальная версия Python и список библиотек для работы приложения.

Когда нужно: всегда, в любом проекте.

[project]
name = "myproject"
version = "0.1.0"
description = "Описание проекта"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
    "fastapi>=0.115",
    "uvicorn[standard]>=0.34",
]

[dependency-groups] — группы зависимостей

Что делает: разделяет библиотеки по назначению. dev — инструменты для разработчика (линтеры, тесты, форматтеры). test — только для тестов. Обычный пользователь, который ставит ваше приложение, не получает dev-зависимости.

Когда нужно: всегда, когда для разработки нужны инструменты, не требующиеся конечному пользователю.

[dependency-groups]
dev = [
    "pytest>=8.0",
    "ruff>=0.11",
    "mypy>=1.13",
]
test = [
    "pytest-cov>=5.0",
]

[tool.uv] — корневая секция настроек uv

Все дальнейшие настройки живут внутри [tool.uv]. Это главная секция, через которую uv понимает, как управлять вашим проектом.


managed — кто управляет виртуальным окружением

Что делает: по умолчанию uv сам создаёт папку .venv, устанавливает туда зависимости и следит за актуальностью. Если выключить (false), uv не трогает venv — вы управляете им вручную.

Когда нужно: false — если venv уже создан другим инструментом или вы хотите полный контроль. Обычно трогать не надо.

[tool.uv]
managed = false

required-version — какую версию uv требовать

Что делает: если у пользователя версия uv старее указанной — uv откажется работать и скажет обновиться. Гарантирует, что вся команда использует совместимую версию.

Когда нужно: командная разработка, CI/CD — чтобы избежать «у меня работает, а у тебя нет».

[tool.uv]
required-version = ">=0.6.0"

default-groups — какие группы зависимостей ставить по умолчанию

Что делает: указывает, какие группы из [dependency-groups] устанавливать при uv sync и uv run без дополнительных флагов. По умолчанию — только основные зависимости (без dev).

Когда нужно: если dev-инструменты (ruff, mypy) должны быть всегда доступны в проекте.

[tool.uv]
default-groups = ["dev"]

Что делает: uv хранит все скачанные библиотеки в глобальном кеше и «прокидывает» их в .venv одним из способов:

  • clone (Mac/Linux по умолчанию) — Copy-on-Write: быстро, не занимает лишнего места, файлы независимы после копирования.
  • hardlink (Windows по умолчанию) — жёсткие ссылки: ещё быстрее, но файл в venv и кеше — один и тот же.
  • copy — честное копирование: медленнее, но venv полностью независим.
  • symlink — символические ссылки: опасно, uv cache clean сломает venv.

Когда нужно: copy — для Docker-образов (иначе venv будет ссылаться на несуществующий кеш). В остальных случаях не трогать.

[tool.uv]
link-mode = "copy"

compile-bytecode — сразу компилировать .pyc

Что делает: при установке пакета сразу создаёт скомпилированные .pyc-файлы. Первый запуск приложения становится быстрее, установка — чуть дольше.

Когда нужно: продакшен-окружение, Docker-образы.

[tool.uv]
compile-bytecode = true

python-preference — какую установку Python использовать

Что делает: managed (по умолчанию) — использовать Python, скачанный через uv python install. system — использовать системный Python (тот, что уже стоит в /usr/bin/python3).

Когда нужно: system — на сервере, где Python уже настроен админом и вы не хотите ставить ещё один.

[tool.uv]
python-preference = "system"

index-strategy — где и как искать пакеты

Что делает: когда у вас несколько индексов (PyPI + приватный сервер пакетов), эта настройка определяет поведение:

  • first-index (по умолчанию) — ищет пакет в первом индексе, где он нашёлся. Безопасно: злоумышленник не сможет подменить пакет через второй индекс.
  • unsafe-best-match — ищет во всех индексах и берёт лучшую версию. Быстрее, но риск «dependency confusion»-атак.

Когда нужно: unsafe-best-match — если есть только проверенные индексы и нужно ускорить разрешение.

[tool.uv]
index-strategy = "first-index"

prerelease — разрешить бета-версии пакетов

Что делает: по умолчанию uv избегает pre-release версий (0.5.0b1, 1.0.0rc1). "allow" разрешает их установку.

Когда нужно: когда библиотека ещё не вышла официально, но вам нужна новая фича или исправление.

[tool.uv]
prerelease = "if-necessary-or-explicit"

constraint-dependencies — «эту версию — никогда»

Что делает: запрещает определённые версии пакетов при разрешении зависимостей. Работает и для транзитивных зависимостей (те, которые подтягиваются другими библиотеками).

Когда нужно: новая версия чужой библиотеки всё ломает, и вы хотите временно запретить её установку.

[tool.uv]
constraint-dependencies = ["grpcio<1.65", "protobuf<5.0"]

override-dependencies — «используй только эту версию»

Что делает: принудительно заменяет версию пакета на указанную, даже если другие библиотеки требуют другую. Мощнее, чем constraint. Можно указать глобально или только для зависимостей конкретного пакета.

Когда нужно: баг в чужой библиотеке уже исправлен, но она не выпустила обновление. Или конфликт зависимостей, который нельзя решить иначе.

[tool.uv]
override-dependencies = [
    # Глобально: всегда werkzeug 2.3.0
    "werkzeug==2.3.0",
    # Только когда flask 3.0.0 → заменить itsdangerous на 2.1.2
    { package = { name = "flask", version = "3.0.0" }, dependencies = ["itsdangerous==2.1.2"] },
]

conflicts — несовместимые библиотеки

Что делает: явно говорим uv: «эти две штуки нельзя ставить вместе». Полезно, когда у пакета есть взаимоисключающие extras (дополнительные возможности).

Когда нужно: библиотека предлагает два несовместимых дополнения (например, mylib[cuda] и mylib[cpu]), и вы хотите гарантировать, что пользователь не поставит оба.

[tool.uv]
conflicts = [
    [
        { extra = "cuda" },
        { extra = "cpu" },
    ],
]

[[tool.uv.index]] — откуда качать пакеты

Что делает: настраивает источники пакетов. Можно добавить приватный PyPI-сервер компании, PyTorch-индекс для GPU-версий, внутреннее зеркало. Порядок важен: uv ищет пакеты по очереди.

Когда нужно: приватные пакеты компании, ускорение через локальное зеркало, специфические индексы (PyTorch, TensorFlow).

[[tool.uv.index]]
name = "pypi"
url = "https://pypi.org/simple"
default = true                     # основной индекс

[[tool.uv.index]]
name = "private"
url = "https://packages.company.com/simple"
publish-url = "https://packages.company.com/upload"

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cu124"
explicit = true                    # использовать только когда явно указан

[tool.uv.sources] — откуда брать конкретную библиотеку

Что делает: для конкретного пакета можно указать нестандартный источник: Git-репозиторий, локальную папку, workspace-пакет. Позволяет разрабатывать библиотеку локально и сразу использовать её в проекте.

Когда нужно: форк чужой библиотеки, ещё не опубликованный пакет, локальная разработка связанных библиотек.

[project]
dependencies = [
    "my-lib",
    "flask",
]

[tool.uv.sources]
# Локальная папка (не редактируемая)
my-lib = { path = "./libs/my-lib" }

# Локальная папка в editable-режиме (меняешь код — сразу видно)
# my-lib = { path = "./libs/my-lib", editable = true }

# Git-репозиторий
flask = { git = "https://github.com/myfork/flask", branch = "fix-bug" }
# или: tag = "v3.1.0", rev = "abc123"

# Workspace-пакет (для монорепозиториев)
# shared-utils = { workspace = true }

[tool.uv.workspace] — монорепозиторий

Что делает: описывает структуру монорепозитория — проекта из нескольких связанных библиотек в одном Git-репозитории. Указывает, в каких папках лежат подпроекты.

Когда нужно: проект вырос, и вы разделили его на независимые библиотеки (ядро, API, утилиты), которые живут в одном репозитории.

[tool.uv.workspace]
members = ["packages/*"]           # все папки внутри packages/

[tool.uv.sources]
shared-utils = { workspace = true }  # зависимость на соседний workspace-пакет

[build-system] — чем собирать проект

Что делает: указывает инструмент для сборки пакета в .whl / .tar.gz. uv_build — быстрый uv-бекенд (рекомендуется). hatchling / setuptools — для совместимости со старыми проектами.

Когда нужно: если планируете публиковать пакет в PyPI (uv publish) или собирать через uv build.

[build-system]
requires = ["uv_build>=0.11.25,<0.12"]
build-backend = "uv_build"

# Альтернативы:
# requires = ["hatchling"]
# build-backend = "hatchling.build"

# requires = ["setuptools>=75", "wheel"]
# build-backend = "setuptools.build_meta"

exclude-newer — игнорировать пакеты новее даты

Что делает: uv делает вид, что пакетов, вышедших позже указанной даты, не существует. Это даёт воспроизводимые сборки: сегодняшний билд гарантированно соберётся так же, как вчерашний.

Когда нужно: CI/CD, строгие продакшен-сборки, отладка проблем с зависимостями.

[tool.uv]
exclude-newer = "2025-01-01T00:00:00Z"

concurrent-builds — сколько пакетов собирать одновременно

Что делает: ограничивает число одновременных сборок пакетов из исходников (sdist). По умолчанию — число ядер CPU.

Когда нужно: CI с ограниченной памятью, Raspberry Pi, слабый сервер — уменьшить до 2.

[tool.uv]
concurrent-builds = 2

Зависимости

Добавление и удаление

uv add requests                         # добавить зависимость
uv add "requests>=2.28,<3"              # с версионными ограничениями
uv add flask click                      # несколько сразу
uv add --dev pytest                     # в dev-зависимости
uv add --group test pytest-coverage     # в именованную группу
uv add git+https://github.com/user/pkg  # из git
uv add "pkg @ git+https://..."          # альтернативный синтаксис
uv add ./local-package                  # из локальной папки
uv add -r requirements.txt              # импорт из requirements.txt

uv remove requests                      # удалить
uv remove flask click                   # несколько сразу

uv lock                                 # обновить lockfile
uv lock --upgrade                       # обновить все до последних версий
uv lock --upgrade-package requests      # обновить конкретный пакет
uv sync                                 # синхронизировать venv с lockfile
uv tree                                 # дерево зависимостей
uv tree --depth 2                       # ограничить глубину

Экспорт зависимостей

uv export --format requirements-txt > requirements.txt
uv export --no-dev --format requirements-txt > requirements.txt   # без dev
uv export --format requirements-txt --output-file requirements.txt

Запуск и окружение

uv run — универсальный запуск

uv run python                          # запустить Python в venv проекта
uv run script.py                       # запустить скрипт
uv run pytest                          # запустить pytest (из dev-зависимостей)
uv run python -c "import sys; print(sys.version)"

# С конкретной версией Python
uv run --python 3.11 script.py

# С дополнительной зависимостью (временной)
uv run --with httpx python -c "import httpx; print(httpx.__version__)"

# Без изоляции (доступ к проекту + временная зависимость)
uv run --with pytest .

uv run автоматически проверяет актуальность lockfile и venv перед запуском.

uv sync — ручная синхронизация

uv sync                    # установить зависимости из lockfile
uv sync --no-dev           # без dev-зависимостей
uv sync --group test       # только основная группа + test
uv sync --frozen           # только из lockfile (не обновлять)
uv sync --reinstall        # переустановить все пакеты

Ручная активация venv

source .venv/bin/activate     # Linux/macOS
.venv\Scripts\activate        # Windows

# uv автоматически находит .venv — активация не обязательна!

Управление версиями Python

uv python list                # установленные + доступные для установки
uv python install 3.12        # установить Python 3.12
uv python install 3.11 3.12  # несколько версий
uv python install pypy@3.10  # PyPy
uv python uninstall 3.11      # удалить
uv python find 3.12           # найти путь к интерпретатору
uv python pin 3.12            # закрепить версию в .python-version

# В pyproject.toml
# requires-python = ">=3.11"

Скрипты (inline dependencies)

Скрипты с зависимостями прямо в коде — не нужен pyproject.toml:

#!/usr/bin/env -S uv run
# /// script
# requires-python = ">=3.12"
# dependencies = [
#     "requests",
#     "rich",
# ]
# ///

import requests
from rich import print

resp = requests.get("https://api.github.com")
print(f"[bold green]Status:[/] {resp.status_code}")
# Создать скрипт
uv init --script fetch.py
uv add requests --script fetch.py        # добавить зависимость в скрипт
uv remove requests --script fetch.py     # удалить
uv run fetch.py                          # запустить
uv run --with rich fetch.py              # + временная зависимость

# Сделать исполняемым
chmod +x fetch.py
./fetch.py                               # shebang всё сделает сам!

uv tool — глобальные инструменты

Аналог pipx. Инструменты ставятся в изолированные окружения, их бинарники — в PATH.

# Запуск без установки (временное окружение)
uv tool run ruff check .                # полная команда
uvx ruff check .                        # короткий алиас!

# Установка (глобально)
uv tool install ruff                    # установить
uv tool install "ruff>=0.5"             # с версией
uv tool install ruff@latest             # последняя версия

# С дополнительными зависимостями
uv tool install ruff --with ruff-lsp
uvx --with pandas python -c "import pandas"

# Управление
uv tool list                            # список установленных
uv tool upgrade ruff                    # обновить один
uv tool upgrade --all                   # обновить все
uv tool uninstall ruff                  # удалить

# Версионирование
uvx ruff@0.5.0 check .                 # конкретная версия
uvx ruff@latest check .                # принудительно последняя
uv tool install ruff --reinstall        # переустановить

# Проброс дополнительных исполняемых файлов
uv tool install ansible --with-executables-from ansible-core --with-executables-from ansible-lint

# Обновление PATH (если uv предупреждает)
uv tool update-shell

Разница uvx vs uv tool install:

  • uvx — одноразовый запуск, окружение в кеше (может быть удалено)
  • uv tool install — постоянная установка, бинарник в PATH

uv pip — совместимость с pip

Полный интерфейс pip с uv-скоростью. Для проектов без pyproject.toml.

# Установка
uv pip install requests
uv pip install "requests==2.28.1"
uv pip install -r requirements.txt
uv pip install -e .                    # editable install

# Компиляция (pip-tools аналог)
uv pip compile requirements.in -o requirements.txt
uv pip compile requirements.in --generate-hashes -o requirements.txt
uv pip compile pyproject.toml -o requirements.txt  # из pyproject.toml

# Синхронизация (точное соответствие)
uv pip sync requirements.txt           # установить + удалить лишнее

# Остальные команды
uv pip list                            # список пакетов
uv pip list --outdated                 # устаревшие
uv pip show requests                   # инфо о пакете
uv pip uninstall requests              # удалить
uv pip freeze > requirements.txt       # заморозить
uv pip check                           # проверить конфликты

Сборка и публикация

# Сборка
uv build                               # sdist + wheel
uv build --wheel                       # только wheel
uv build --sdist                       # только sdist
# Артефакты: dist/*.tar.gz, dist/*.whl

# Управление версией
uv version                             # показать текущую
uv version --bump major                # 0.1.0 → 1.0.0
uv version --bump minor                # 1.0.0 → 1.1.0
uv version --bump patch                # 1.1.0 → 1.1.1
uv version --bump beta                 # 1.1.0 → 1.1.0b1
uv version --bump rc                   # 1.1.0b1 → 1.1.0rc1
uv version --bump stable               # 1.1.0rc1 → 1.1.0

# Публикация в PyPI
uv publish                             # в PyPI (нужен токен)
uv publish --token $PYPI_TOKEN
uv publish --publish-url https://test.pypi.org/legacy/  # Test PyPI

Workspace (монорепозитории)

# pyproject.toml (корень workspace)
[tool.uv.workspace]
members = ["packages/*"]

[tool.uv.sources]
mylib = { workspace = true }
uv init --lib packages/mylib            # библиотека в workspace
uv add mylib                            # в корне — ссылка на workspace-пакет
uv run --package mylib pytest           # запустить в контексте конкретного пакета

Docker

# Multi-stage build с uv
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder
WORKDIR /app
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy

COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-install-project --no-dev

COPY . .
RUN uv sync --frozen --no-dev

FROM python:3.12-slim
COPY --from=builder /app /app
ENV PATH="/app/.venv/bin:$PATH"
CMD ["python", "main.py"]

docker-compose

services:
  app:
    build: .
    ports: ["8000:8000"]
    environment:
      - UV_LINK_MODE=copy

CI/CD (GitHub Actions)

- uses: astral-sh/setup-uv@v5
  with:
    version: "latest"
    enable-cache: true

- run: uv sync --frozen
- run: uv run pytest
- run: uv run ruff check .
# Кеширование для ускорения
- uses: astral-sh/setup-uv@v5
  with:
    enable-cache: true
    cache-dependency-glob: "uv.lock"

Конфигурация

Переменные окружения

export UV_LINK_MODE=copy                # режим линковки: clone/copy/hardlink/symlink
export UV_COMPILE_BYTECODE=1            # компилировать .pyc при установке
export UV_PROJECT_ENVIRONMENT=/path/to/venv  # путь к venv (вместо авто-обнаружения)
export UV_NO_CACHE=1                    # отключить кеш
export UV_INDEX_URL=https://...         # индекс пакетов по умолчанию

Кеш

uv cache clean                          # очистить кеш
uv cache dir                            # путь к папке кеша
uv cache prune                          # удалить устаревшие записи из кеша

Типовые сценарии

Старт нового проекта с нуля

uv init myproject --python 3.12
cd myproject
uv add fastapi uvicorn[standard]
uv add --dev pytest pytest-cov ruff
uv run uvicorn myproject.main:app --reload

Миграция с pip + venv

# Было:
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# Стало:
uv init                           # один раз
uv add -r requirements.txt        # теперь управляется через uv
uv sync
uv run python script.py

Миграция с Poetry

# Poetry → uv: uv читает pyproject.toml
uv init
uv add -r <(poetry export -f requirements.txt --without-hashes)   # разовый импорт
uv sync
# pyproject.toml уже готов — uv понимает формат Poetry

Миграция с pyenv

pyenv install 3.12     # было
uv python install 3.12 # стало

Миграция с pipx

pipx install ruff      # было
uv tool install ruff   # стало

Частые ошибки

Ошибка Причина Решение
uv run не видит пакет Забыт uv add uv add pkg перед использованием
ModuleNotFoundError после uv sync Виртуальное окружение не активно uv run python вместо python
uv.lock конфликтует с pyproject.toml Изменили зависимости вручную uv lock --upgrade
uv tool install — команда не найдена Бинарная папка не в PATH uv tool update-shell
Docker: venv не работает VENV использует абсолютные пути UV_LINK_MODE=copy
Не та версия Python Проект закреплён в .python-version uv python pin 3.12
C-расширения не собираются Нет компилятора apt install build-essential python3-dev
uv sync --frozen падает lockfile устарел uv lock без --frozen
uv run работает медленно Холодный кеш Второй запуск мгновенный
uv run блокирует на 30+ сек Разрешение зависимостей Используй --frozen после первого uv sync

Таблица замен

Старый инструмент uv-команда
python -m venv .venv uv venv (или авто при uv init)
pip install pkg uv add pkg или uv pip install pkg
pip install -r requirements.txt uv add -r requirements.txt
pip freeze > requirements.txt uv export --format requirements-txt
pip install -e . uv pip install -e .
pip-compile requirements.in uv pip compile requirements.in
pip-sync requirements.txt uv pip sync requirements.txt
pipx install tool uv tool install tool
pipx run tool uvx tool
pyenv install 3.12 uv python install 3.12
poetry add pkg uv add pkg
poetry run cmd uv run cmd
twine upload dist/* uv publish
python -m build uv build

Ресурсы

Что дальше


Связанные шпаргалки: Python, FastAPI, Django, Параллелизм, Rust