Перейти к содержанию

Python UV: полное руководство по быстрому менеджеру пакетов Python

Что такое Python UV?

UV — современный высокопроизводительный менеджер и установщик Python-пакетов, написанный на Rust. Он выступает заменой традиционным инструментам управления пакетами вроде pip, давая существенный выигрыш в скорости, надёжности и разрешении зависимостей.

UV относится к новому поколению менеджеров пакетов Python и призван решать типичные проблемы экосистемы: медленная установка, конфликты зависимостей и сложность управления окружениями. Это достигается за счёт архитектуры и эффективной реализации: UV в 10–100 раз быстрее традиционных менеджеров.

Чем выделяется UV:

  • Экономичная работа с памятью, в том числе в крупных проектах
  • Надёжная фиксация зависимостей и воспроизводимые окружения
  • Поддержка современных стандартов упаковки
  • Встроенное управление виртуальными окружениями
  • Совместимость с существующими инструментами и workflow
  • Очень быстрая установка пакетов и разрешение зависимостей

UV подходит и для небольших личных проектов, и для крупных приложений на Python. В этом руководстве разобраны все нужные аспекты UV, чтобы можно было сразу начать им пользоваться.

Различия между UV, Poetry, PIP, Conda и virtualenv

Перед переходом на новый инструмент обычно спрашивают: «Чем он лучше того, что я уже использую?». В области зависимостей и управления проектами в Python чаще всего встречаются:

Ниже — сравнение UV с каждым из них, чтобы решить, подходит ли UV под ваши задачи.

UV и PIP / virtualenv

PIP и virtualenv долгое время были основными инструментами для установки пакетов и создания виртуальных окружений. UV даёт несколько преимуществ:

  • Единое управление окружением: virtualenv только создаёт окружение, PIP только ставит пакеты; UV объединяет обе функции в одном инструменте и упрощает workflow.
  • Скорость: реализация на Rust делает UV заметно быстрее PIP при установке и разрешении зависимостей — то, на что у PIP уходят минуты, UV часто делает за секунды.

UV сохраняет совместимость с экосистемой PIP и при этом устраняет её ограничения. Он может использовать те же requirements.txt и индексы пакетов, поэтому миграция проходит безболезненно. Основные отличия:

  • Воспроизводимость: подход UV с lockfile даёт одинаковые окружения на разных системах, чего не гарантирует простой requirements.txt.
  • Обработка ошибок: UV выдаёт более понятные сообщения и лучше разрешает конфликты зависимостей.
  • Память: UV использует заметно меньше памяти, чем PIP, при установке и разрешении зависимостей.
  • Производительность: параллельная загрузка и оптимизированный резолвер делают UV в 10–100 раз быстрее PIP на крупных проектах.

PIP и virtualenv по-прежнему пригодны, но современная архитектура UV и объединённый функционал делают его удобной заменой для тех, кому важны скорость и простой workflow. Возможность подключать UV к существующим проектам без ломки процессов особенно полезна командам, которые хотят постепенно обновлять свой Python-инструментарий.

UV и Conda

Кто не использует PIP и virtualenv, часто переходит на Conda, и на то есть причины:

  • Дистрибутив Anaconda содержит много предустановленных научных пакетов, что удобно для специалистов по данным
  • Встроенная поддержка разных версий Python и переключение между ними
  • Окружения Conda лучше изолированы и воспроизводимы на разных ОС
  • Удобство для сложных научных окружений с NumPy, SciPy, TensorFlow и т.п.
  • Conda управляет не только Python-пакетами, но и системными зависимостями

Тем не менее и заядлым пользователям Conda имеет смысл присмотреться к UV. Быстрая установка и разрешение зависимостей в UV могут сильно ускорить подготовку окружения по сравнению с нередко медленной Conda. Меньший расход ресурсов — меньше памяти и быстрый старт. UV хорошо стыкуется со стандартами и инструментами упаковки Python, поэтому проще вписывается в общую экосистему. Для проектов, где не нужны не-Python пакеты Conda, UV даёт более простой и быстрый вариант и может заметно улучшить рабочий процесс.

UV и Poetry

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

  • Современный подход к управлению проектами на Python
  • Публикация пакетов в PyPI
  • Lockfile для воспроизводимых окружений
  • Инициализация и структура проекта
  • Управление зависимостями и виртуальными окружениями

Главное отличие UV — высокая скорость и малый расход ресурсов. Poetry уже серьёзный шаг вперёд по сравнению с классическими инструментами, а UV за счёт реализации на Rust поднимает производительность ещё выше. Плюс совместимость UV с текущей упаковкой Python позволяет использовать его вместе с pip и другими инструментами — гибкость, которой иногда не хватает более «жёсткому» подходу Poetry.

Сводная таблица рассмотренных отличий:

Характеристика UV PIP + virtualenv Conda Poetry
Реализация Rust Python Python Python
Скорость В 10–100 раз быстрее pip Базовый уровень Медленнее pip Быстрее pip
Использование памяти Очень эффективно Выше Высокое Умеренное
Управление окружениями Встроено Нужны отдельные инструменты Встроено Встроено
Разрешение зависимостей Быстрый современный резолвер Базовый Подробный Современный резолвер
Не-Python пакеты Нет Нет Да Нет
Lockfile Да Нет (только requirements.txt) Да Да
Структура проекта Да Нет Нет Да
Публикация пакетов Да Да (с twine) Да Да
Совместимость Работает с экосистемой pip Стандартный инструмент Python Своя экосистема Более жёсткий подход
Обработка ошибок Понятные сообщения Базовый уровень Хорошо Хорошо
Ресурсы Минимальные Умеренные Большие Умеренные
Фокус на научных вычислениях Нет Нет Да Нет
Одинаковое поведение на платформах Да Ограничено Отлично Хорошо

Если переход на UV кажется оправданным, читайте дальше.

Начало работы с UV в Python-проектах

Ниже — как начать проект с нуля с помощью UV. Миграция существующих проектов на UV разобрана в одной из следующих секций.

Установка UV

UV можно установить системно через cURL в macOS и Linux:

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

В Windows — через PowerShell (желательно с правами администратора):

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

UV также доступен через Homebrew:

$ brew install uv

Установка через PIP поддерживается, но не рекомендуется:

$ pip install uv  # Желательно в активированном виртуальном окружении

Проверить установку можно командой uv version:

$ uv version
uv 0.4.25 (97eb6ab4a 2024-10-21)

Инициализация нового проекта

Работа с проектами — основа UV. Новый пустой проект создаётся командой uv init:

$ uv init explore-uv
Initialized project explore-uv at /Users/bexgboost/projects/explore-uv

Команда создаёт каталог explore-uv с таким содержимым:

$ cd explore-uv
$ tree -a
.
├── .gitignore
├── .python-version
├── README.md
├── hello.py
└── pyproject.toml

Инициализируется Git, добавляются .gitignore и пустой README.md. В .python-version указана версия Python для проекта, в pyproject.toml — метаданные и зависимости. Файл hello.py — пример для быстрого старта.

Подробнее о создании проектов см. в документации UV.

Добавление первых зависимостей

В UV создание окружения и установка зависимостей объединены в одну команду — uv add:

$ uv add scikit-learn xgboost
Using CPython 3.9.20 interpreter at: /opt/homebrew/opt/python@3.9/bin/python3.9
Creating virtual environment at: .venv
Resolved 6 packages in 1.78s
⠧ Preparing packages... (2/5)
Prepared 5 packages in 1m 23s
Installed 5 packages in 45ms
 + joblib==1.4.2
 + numpy==2.0.2
 + scikit-learn==1.5.2
 ...

При первом запуске add UV создаёт виртуальное окружение в текущем каталоге и ставит указанные зависимости. Дальше используется уже существующее окружение, обновляются или добавляются только запрошенные пакеты.

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

После каждого add обновляются pyproject.toml и uv.lock. Пример pyproject.toml после установки Scikit-learn и XGBoost:

$ cat pyproject.toml
[project]
name = "explore-uv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.9"
dependencies = [
    "scikit-learn>=1.5.2",
    "xgboost>=2.0.3",
]

Чтобы убрать зависимость из окружения и из pyproject.toml, используется uv remove. Пакет и все его транзитивные зависимости будут удалены:

$ uv remove scikit-learn

Управление зависимостями подробнее разобрано ниже.

Запуск Python-скриптов с UV

После установки зависимостей можно работать со скриптами как обычно. UV предлагает несколько способов запуска:

Запуск скрипта напрямую — команда uv run и имя скрипта вместо привычного python script.py:

$ uv run hello.py

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

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

Выбор версии Python — важная часть управления зависимостями. В UV для этого есть отдельные команды. Ниже — работа с командой uv python.

Список установленных версий Python

Часто в системе уже есть Python, и UV по умолчанию находит такие установки. Список версий, которые видит UV:

$ uv python list --only-installed
cpython-3.13.0-macos-aarch64-none     /opt/homebrew/opt/python@3.13/bin/python3.13 -> ...
cpython-3.12.7-macos-aarch64-none     /opt/homebrew/opt/python@3.12/bin/python3.12 -> ...
cpython-3.12.5-macos-aarch64-none     /Users/bexgboost/miniforge3/bin/python3.12
...

Так можно увидеть версии Python, установленные через Conda, Homebrew и т.д.

Смена версии Python в текущем проекте

Версию Python для текущего проекта UV можно менять в любой момент, если она удовлетворяет ограничениям в pyproject.toml. Например, при таком условии:

requires-python = ">=3.9"

можно выставить в .python-version любую версию не ниже 3.9, например 3.11.7, после чего выполнить uv sync.

Сначала UV ищет подходящую версию среди уже установленных. Если её нет, UV скачивает и устанавливает её в каталог вида /Users/username/.local/share/uv/python. В каталоге проекта создаётся новое виртуальное окружение, заменяя старое.

В новом окружении нет зависимостей из pyproject.toml, их нужно установить:

$ uv pip install -e .

Иногда команды uv могут завершаться ошибкой «Permission Denied». В таких случаях на macOS/Linux можно использовать sudo или запускать терминал с правами администратора в Windows. Часто лучше изменить владельца каталога UV на текущего пользователя:

$ sudo chown -R $USER ~/.local/share/uv  # macOS или Linux

Подробнее об управлении версиями Python в UV см. в документации.

Инструменты UV: что это и как использовать

Некоторые Python-пакеты предоставляют консольные утилиты: black для форматирования, flake8 для линтинга, pytest для тестов, mypy для проверки типов и т.д. В UV для них есть два варианта:

  1. Команда uv tool run:
$ uv tool run black hello.py
  1. Более короткий вариант — uvx:
$ uvx black hello.py

В обоих случаях UV создаёт временное виртуальное окружение в своём кэше, ставит туда нужный инструмент и запускает его. То есть консольные утилиты можно использовать, не устанавливая их в окружение проекта — зависимости проекта остаются чище, а запуск быстрее.

Кратко об интерфейсе запуска инструментов:

  • Удобно для эпизодического использования инструментов разработки
  • Окружения в кэше создаются по требованию
  • При очистке кэша UV временные окружения удаляются
  • Работает с любым пакетом, предоставляющим консольные команды (flake8, mypy, black, pytest и т.д.)

Подробнее см. раздел UV Tools в документации.

Lockfile в UV

Lockfile (uv.lock) — важная часть управления зависимостями в UV. При установке зависимостей через uv add UV автоматически создаёт и обновляет файл uv.lock. Он нужен чтобы:

  • Ускорять установку: UV использует зафиксированные версии и не разрешает зависимости заново
  • Избегать «dependency hell», сохраняя одни и те же версии пакетов
  • Обеспечивать воспроизводимые сборки на разных окружениях
  • Фиксировать точные версии всех зависимостей и подзависимостей

UV сам управляет lockfile, править его вручную не требуется. Файл стоит коммитить в репозиторий, чтобы у всех разработчиков были одинаковые версии зависимостей.

Чем lockfile отличается от requirements.txt

И lockfile, и requirements.txt описывают зависимости, но задачи у них разные. Lockfile хранит точные версии пакетов и полное дерево зависимостей и обеспечивает одинаковое окружение при разработке. requirements.txt обычно перечисляет только прямые зависимости и поддерживается многими инструментами.

Lockfile важен для разработки: воспроизводимые сборки и меньше конфликтов. requirements.txt удобнее для деплоя или когда код передаётся пользователям, не использующим UV, а также для сервисов и инструментов, не поддерживающих формат lockfile UV.

Можно вести оба: использовать lockfile UV в разработке и генерировать requirements.txt для деплоя. Экспорт из lockfile в requirements.txt:

$ uv export -o requirements.txt

Получится текстовый файл с зафиксированными версиями на основе lockfile — зависимости проекта можно передать в стандартном формате, сохраняя преимущества UV при разработке.

Подробнее об управлении lockfile см. в документации.

Продвинутое управление зависимостями в UV

Ниже — более гибкие приёмы: обновление зависимостей, опциональные зависимости и группы зависимостей.

Обновление зависимостей

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

  1. Установить последнюю версию пакета:
$ uv add requests
  1. Установить конкретную версию:
$ uv add requests=2.1.2
  1. Изменить ограничения по версии:
$ uv add 'requests<3.0.0'
  1. Сделать зависимость платформо-специфичной:
$ uv add 'requests; sys_platform="linux"'

Опциональные зависимости

Опциональные зависимости не обязательны для основной функциональности, но нужны для отдельных возможностей. Например, у Pandas есть extras excel и plot, чтобы не ставить парсеры Excel и matplotlib без явного запроса. Обычно их ставят так: pip install pandas[plot, excel].

В UV синтаксис немного другой. Сначала добавляется основной пакет:

$ uv add pandas

Затем опциональные зависимости:

$ uv add pandas --optional plot excel

После разрешения они попадут в pyproject.toml в таком виде:

[project]
name = "explore-uv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.9"
dependencies = [
    "pandas>=2.2.3",
    "requests>=2.32.3",
]
[project.optional-dependencies]
plot = [
    "excel>=1.0.1",
    ...
]

Группы зависимостей

Группы позволяют разнести зависимости по смыслу: разработка, тесты, документация и т.д. Так удобнее отделять продакшен-зависимости от вспомогательных.

Добавление зависимости в группу — флаг --group:

$ uv add --group group_name package_name

Установка только нужных групп задаётся флагами --group, --only-group и --no-group.

Переход с PIP и Virtualenv на UV

Переход с PIP и virtualenv на UV упрощается тем, что UV совместим с существующими стандартами упаковки Python. Пошагово:

1. Проект на virtualenv и pip

Если проект уже использует virtualenv и pip, сначала создайте requirements.txt из текущего окружения (если его ещё нет):

$ pip freeze > requirements.txt

Затем инициализируйте проект UV в том же каталоге:

$ uv init .

Установите зависимости из requirements.txt:

$ uv pip install -r requirements.txt

2. Замена типичных команд pip/virtualenv

Краткая сводка соответствия команд:

Команда pip/virtualenv Эквивалент в UV
python -m venv .venv uv venv
pip install package uv add package
pip install -r requirements.txt uv pip install -r requirements.txt
pip uninstall package uv remove package
pip freeze uv pip freeze
pip list uv pip list

После миграции старый каталог виртуального окружения можно удалить и пользоваться окружением UV. При необходимости можно по-прежнему вызывать команды в стиле pip через слой совместимости uv pip.

Заключение

UV заметно продвигает управление Python-пакетами: современная, быстрая и эффективная альтернатива традиционным инструментам. Основные плюсы:

  • Низкое потребление памяти и ресурсов
  • Быстрое разрешение зависимостей и поддержка lockfile
  • Встроенное управление виртуальными окружениями
  • Хорошая интеграция с текущими стандартами упаковки Python
  • Высокая скорость, в 10–100 раз быстрее pip

И для новых проектов, и при переносе существующих UV даёт удобный способ улучшить рабочий процесс. Совместимость с привычными инструментами упрощает переход без ломки текущих процессов.

По мере развития экосистемы Python такие инструменты, как UV, показывают, как современные технологии вроде Rust могут улучшать разработку, сохраняя простоту и доступность, важные для сообщества Python.

Дополнительные материалы:

Частые вопросы по Python UV

UV быстрее pip при управлении пакетами?

Да. UV заметно быстрее pip: установка пакетов и разрешение зависимостей ускоряются в 10–100 раз за счёт реализации на Rust и параллельной загрузки. Для крупных проектов то, на что у pip уходят минуты, UV часто делает за секунды.

Можно ли использовать UV с существующими requirements.txt?

Да. UV совместим с requirements.txt и может установить зависимости командой uv pip install -r requirements.txt. При этом сохраняется совместимость с экосистемой Python и улучшаются производительность и управление зависимостями.

Чем UV выгоднее Poetry и Conda?

  • Более гибкий подход по сравнению с жёсткой структурой Poetry
  • Проще в использовании по сравнению с Conda
  • Лучшая совместимость с текущими Python-инструментами
  • Меньше потребление памяти и ресурсов
  • Высокая скорость за счёт реализации на Rust

Conda удобна для не-Python пакетов, Poetry — для структуры проекта; UV даёт удачный баланс скорости и совместимости.

Поддерживает ли UV виртуальные окружения?

Да. В UV встроено управление виртуальными окружениями. При первом запуске uv add в проекте окружение создаётся и дальше поддерживается автоматически. Создание окружения и установка пакетов объединены в одном инструменте, в отличие от связки pip и virtualenv.