Если вы пришли в Python из мира PHP и Composer, привычная история с зависимостями выглядит странно: отдельно pyenv для версий интерпретатора, отдельно venv для окружений, pip для установки пакетов, pip-tools для лок-файлов и pipx для CLI-утилит. Пять инструментов там, где в других экосистемах хватает одного. Инструмент uv от команды Astral (авторов линтера Ruff) закрывает все эти задачи одним бинарником, написанным на Rust, и делает это в десятки раз быстрее. В этой статье разберём uv на практике: установка, создание проекта, управление зависимостями, версии Python, запуск кода и сборка Docker-образов.
Что такое uv и зачем он нужен
uv — это менеджер пакетов и проектов для Python «всё в одном». Он заменяет сразу несколько привычных инструментов:
pipиpip-tools— установка пакетов и формирование лок-файлов;virtualenvиvenv— создание виртуальных окружений;pyenv— установка и переключение версий Python;pipx— установка изолированных CLI-утилит.
Ключевое преимущество — скорость: за счёт параллельного резолвинга зависимостей, глобального кеша и реализации на Rust uv работает значительно быстрее связки pip + virtualenv. Бинарник не требует предустановленного Python или Rust, поддерживает Linux, macOS и Windows, а лок-файл uv.lock кроссплатформенный и обеспечивает воспроизводимые сборки.
Установка
Самый простой способ — официальный установочный скрипт. Он не требует ни Python, ни прав root:
# Linux и macOS
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
uv также доступен через Homebrew (brew install uv), pipx и даже через обычный pip install uv. После установки проверьте версию и при необходимости обновите сам uv:
uv --version
uv self update
Создание нового проекта
Команда uv init разворачивает скелет проекта. Это аналог composer init, только сразу с настройкой окружения:
uv init hello-world
cd hello-world
uv создаст набор файлов: pyproject.toml с метаданными проекта, .python-version с версией интерпретатора, README.md, main.py и инициализирует git-репозиторий. Сам pyproject.toml выглядит лаконично:
[project]
name = "hello-world"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
dependencies = []
Виртуальное окружение .venv и лок-файл uv.lock создаются автоматически при первом вызове проектной команды — uv run, uv sync или uv lock. Запустим стартовый скрипт:
uv run main.py
# Hello from hello-world!
Управление зависимостями
Добавление пакета через uv add сразу обновляет pyproject.toml, лок-файл и окружение — три действия одной командой:
# Добавить зависимость
uv add requests
# Зафиксировать версию
uv add 'requests==2.31.0'
# Зависимость из git
uv add git+https://github.com/psf/requests
# Удалить пакет
uv remove requests
Если вы переезжаете со старого проекта, импортировать зависимости из requirements.txt можно одной командой:
uv add -r requirements.txt
Обновление конкретного пакета выполняется через uv lock с флагом --upgrade-package: он подтянет свежую совместимую версию, не трогая остальной лок-файл:
uv lock --upgrade-package requests
Файл uv.lock — это человекочитаемый TOML, который содержит точные разрешённые версии всех зависимостей. Его обязательно нужно коммитить в репозиторий, но не редактировать руками: им управляет сам uv.
Запуск кода: uv run и uv sync
Главная рабочая команда — uv run. Перед каждым запуском uv проверяет, что лок-файл соответствует pyproject.toml, а окружение — лок-файлу, и при необходимости синхронизирует их. Вам не нужно вручную активировать venv:
uv add flask
uv run -- flask run -p 3000
# Запуск произвольного скрипта
uv run example.py
Если вы предпочитаете классический подход с активацией окружения, используйте uv sync, который приводит .venv в соответствие с лок-файлом:
uv sync
source .venv/bin/activate # Windows: .venv\Scripts\activate
flask run -p 3000
Управление версиями Python
uv умеет скачивать и устанавливать сами интерпретаторы — отдельный pyenv больше не нужен:
# Установить конкретную версию
uv python install 3.13
# Посмотреть доступные и установленные версии
uv python list
# Закрепить версию для текущего проекта
uv python pin 3.13
Команда uv python pin запишет выбранную версию в .python-version, и все последующие команды проекта будут использовать именно её.
uv в Docker
Astral публикует официальные образы в ghcr.io/astral-sh/uv — как «distroless» с одним бинарником для копирования в свои сборки, так и production-образы на базе Debian, Alpine и официальных python-образов. Базовый приём — скопировать бинарник uv из официального образа, обязательно закрепив версию:
FROM python:3.12-slim-trixie
# Закрепляем конкретную версию uv ради воспроизводимости
COPY --from=ghcr.io/astral-sh/uv:0.11.23 /uv /uvx /bin/
Для реальных приложений выгодно разнести установку зависимостей и копирование кода по разным слоям: зависимости меняются редко, а код — постоянно. Флаг --no-install-project ставит только зависимости, а кеш-маунт ускоряет повторные сборки:
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
# Слой только с зависимостями (кешируется отдельно)
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --no-install-project
# Копируем проект и досинхронизируем
COPY . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked
CMD ["uv", "run", "my_app"]
Несколько практических деталей. Добавьте .venv в .dockerignore — окружение зависит от платформы и должно собираться внутри образа с нуля. Флаг --locked в uv sync гарантирует, что лок-файл актуален, иначе сборка упадёт. Для production включите компиляцию байт-кода переменной ENV UV_COMPILE_BYTECODE=1 — это ускорит старт приложения. А переменная ENV UV_LINK_MODE=copy уберёт предупреждения о невозможности создавать ссылки между кешем и окружением на разных файловых системах.
Совместимость с pip
Если переписывать весь pipeline под проектную модель пока некогда, у uv есть подкоманда uv pip — почти drop-in замена pip с тем же интерфейсом, но в разы быстрее:
# Внутри контейнера система изолирована — можно ставить в системный Python
uv pip install --system ruff
# Установка из requirements.txt
uv pip install -r requirements.txt
# Создать и использовать venv вручную
uv venv /opt/venv
Итоги
uv — это редкий случай, когда новый инструмент действительно упрощает экосистему, а не добавляет ещё один слой поверх существующих. Один бинарник заменяет pip, pyenv, pipx, virtualenv и pip-tools, даёт кроссплатформенный лок-файл для воспроизводимых сборок и работает заметно быстрее привычной связки. Для PHP-разработчиков, которым приходится касаться Python в скриптах, парсерах или DevOps-задачах, uv делает работу с зависимостями такой же предсказуемой, как Composer. Начать просто: установите uv, выполните uv init в новом проекте и добавьте первую зависимость через uv add. А в Docker-сборках official-образы Astral с закреплённой версией и кеш-маунтами дадут быстрый и воспроизводимый pipeline из коробки.