
Привет! Это Леша Жиряков, техлид backend-команды витрины онлайн-кинотеатра KION. В прошлый раз я писал про Msgspec vs DataClasses, а сегодня поговорим о пакетных менеджерах.
В жизни каждого разработчика наступает момент, когда нужно воспользоваться сторонней библиотекой — для работы с данными или отправки запросов в БД. А после выбора библиотеки и версии — использовать менеджер пакетов. Вот какие у него функции:
- установка и удаление пакетов; 
- обновление пакетов; 
- безопасность, или сравнение контрольной суммы пакета; 
- разрешение конфликтов версионирования в зависимостях пакетов. 
В этом посте рассмотрим Poetry и UV, которые могут упростить и ускорить разработку на Python. Покажу, как устанавливать, создавать проекты, сравню производительность. Поехали!
В левом углу ринга — Poetry

Пакетный менеджер Poetry вышел в начале 2018 года благодаря разработчику Себастьяну Юстасу. Слоган проекта: «Легкое управление пакетами и зависимостями на Python». И да, главный плюс инструмента — простота.
- Особенности: всестороннее определение зависимостей, изоляция от системы, интуитивные команды. 
- Количество звезд на GitHub: 32,4 тыс. 
- Открытых Issues: 472. 
- Версия: 2.0.1. 
- Год релиза: 2018. 
- Merge Requests (MRs): участвует главный разработчик и сообщество. 
Установка
В документации нас встречает большое и красное предупреждение, что Poetry всегда нужно устанавливать в выделенной виртуальной среде. Цель — изолировать ее от остальной части системы.
Установить менеджер пакетов можно при помощи pip, pipx, curl и командой для Powershell.
Пример команды для установки:
$ pipx install poetryСоздание проекта
Проект создается при помощи команды:
$ poetry init При выполнении команды в терминале получаем такой вывод (до двоеточия — описание, после двоеточия — значение вводит пользователь):
Package name [testpoetry]:  ProjectWithPoetry            
Version [0.1.0]:  0.1.1
Description []:  Test project for Habr 
Author [A <@gmail.com>, n to skip]:  n
License []:  No
Compatible Python versions [>=3.13]:  >=3.9           
Would you like to define your main dependencies interactively? (yes/no) [yes] no
Would you like to define your development dependencies interactively? (yes/no) [yes] noКаждая строка выглядит довольно просто и понятно. Можно сразу указать название, версию, описание, автора, лицензию, поддерживаемые версии Python и определить зависимости. После этого будет сгенерирован файл pyproject.toml в директории проекта.
Добавляем модули в pyproject.toml и устанавливаем при помощи poetry add:
$ poetry add fastapiУстановка из requirements.txt:
$ poetry add $(cat requirements.txt)Еще в Poetry можно указать группу зависимостей. Например, нам нужно добавить библиотеки для разработки (black и isort) из файла requirements.dev.txt. Тогда команда получится такой:
$ poetry add --group dev $(cat requirements.dev.txt)Теперь откроем файл pyproject.toml и изучим его содержимое:
[project]
name = "projectwithpoetry"
version = "0.1.1"
description = "Test project for Habr"
authors = [
    {name = "Your Name",email = "you@example.com"}
]
license = {text = "No"}
readme = "README.md"
requires-python = ">=3.9"
dependencies = [
    "fastapi (>=0.115.8,<0.116.0)"
]
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.group.dev.dependencies]
black = "^25.1.0"
isort = "^6.0.0"Сразу видны имя проекта, версия, описания и авторы. Зависимости разделяются на основные (dependencies) и для разработки (tool.poetry.group.dev.dependencies).
В правом углу ринга — UV

Лучшее слово, которое характеризует UV, — скорость. Этот инструмент быстро устанавливает пакеты, быстро набирает звезды на GitHub, и даже его название читается быстро! Как комментирует создатель проекта Чарли Марш, причина в том, что он написан на Rust и в механизме кэширования, который оптимизирован для «теплых» операций.
Пакетный менеджер впервые предстал перед публикой в 2024 году и уже успел набрать большую популярность в среде разработки.
- Особенности: в 10 раз быстрее pip и в 30 быстрее Poetry, переход между версиями Python, заменяет собой pip/pip-tools/pipx/pyenv и другие инструменты. 
- Количество звезд на GitHub: 37,2 тыс. 
- Открытых Issues: 1,1 тыс. 
- Версия: 0.5.24. 
- Год релиза: 2024. 
- Merge Requests (MRs): участвует главный разработчик и сообщество. 
Установка
Чтобы установить UV, нужно воспользоваться командами, которые я дал выше. Но к ним добавляется еще и brew.
Самый простой способ установить UV:
$ brew install uvВ документации мы замечаем приятную вишенку на торте — образ Docker:
$ docker pull ghcr.io/astral-sh/uv:0.5.25Создание проекта
Выполняется при помощи команды:
$ uv initПри вводе получаем:
Initialized project `testuv`В директории проекта обнаруживаем автоматически сгенерированный файл с таким содержанием:
[project]
name = "testuv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = []Добавляем модули в pyproject.toml и устанавливаем при помощи uv add:
$ uv add fastapiУстановка из requirements.txt:
$ uv add -r requirements.txtДополнительно установим зависимости для разработки в группу development из файла requirements.dev.txt. В нем указаны библиотеки black и isort.
$ uv add --dev -r requirements.dev.txtФайл pyproject.toml:
[project]
name = "testuv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "fastapi>=0.115.8",
]
[dependency-groups]
dev = [
    "black>=25.1.0",
    "isort>=6.0.0",
]Файл pyproject.toml чуть меньше, чем аналогичный при генерации с помощью Poetry, и не содержит полей «лицензия» и «авторы». Заметно разделение зависимостей — указаны «основные» (dependencies) и «для разработки» (dev).
Чем отличаются Poetry и UV
Poetry — простой, но медленный
Как подметил в своей статье Ларри Ду, опыт использования Poetry похож на проекты Cargo и npm. Если сравнивать с pip, то Poetry предварительно пытается разрешить полный граф зависимостей DAG (англ. Directed Acyclic Graph, ориентированный ациклический граф) и устанавливает зависимости по топологической сортировке. Эта сортировка представляет собой линейное упорядочивание вершин, так что для каждого направленного ребра (u, v) вершина u предшествует вершине v.

Как conda и venv, Poetry может управлять виртуальными средами, которые находятся внутри или за пределами директории проекта. Он генерирует файлы блокировки poetry.lock, а это огромное преимущество для воспроизводимости. К тому же файлы многоплатформенные, а значит, могут быть довольно большими.
Poetry позволяет налегке разрабатывать и публиковать Python-пакеты. Это практически идеальный инструмент, но у него все-таки есть недостатки, которые могут затруднить разработку. Основное — разрешение зависимостей может быть невероятно медленным. Причина — то, как в Python-пакетах указаны зависимости. Изучение зависимостей для каждого возможного пакета в DAG может потребовать большого количества операций через загрузку и парсинг Python wheels.
Разрешаются зависимости в Poetry при помощи алгоритма поиска в глубину, написанном на Python. Для сравнения mamba использует написанные на C++ логические SAT-решатели, которые на порядок быстрее.
Устранение зависимостей для крупных проектов в Poetry в сочетании с созданием многоплатформенных файлов блокировки может занять довольно много времени, особенно при наличии реального конфликта в DAG.
UV — быстрый, но только набирающий обороты
Это многообещающий инструмент управления пакетами в экосистеме Python. Проект призван стать заменой pip и дополнением к Python. Сейчас API нестабильно — на это указывает мажорная версия проекта, которая начинается с 0. Примечательно, что разработка ведется при поддержке компании Astral.sh, основанной Чарли Маршем и создателями линтера ruff — инструмента, который практически в одночасье вытеснил всех конкурентов, когда был выпущен в 2022 году.
UV, как и Poetry, поддерживает pyproject.toml и, как и pip, использует алгоритм обратного отслеживания для разрешения зависимостей. Но есть одно отличие — в UV алгоритм написан на Rust, чем и обосновывается его быстрая скорость работы. Когда дело доходит до разрешения зависимостей, то UV работает быстрее, чем Poetry.
Сравнение производительности
Немного о бенчмарках
Из документации UV — все тесты были рассчитаны на macOS с использованием Python 3.12.4 (для инструментов, отличных от UV) и содержат несколько важных предостережений:
- Производительность тестов может сильно различаться в зависимости от различных операционных и файловых систем. Дело в том, что UV использует разные стратегии установки, основываясь на возможностях файловой системы. 
 Так, в macOS используется рефлинкинг, а в Linux — хардлинкинг.
- Производительность тестов может сильно различаться в зависимости от устанавливаемых пакетов. 
Дальше рассмотрим тесты на примере пакета Trio и его зависимостей, которые указаны в docs-requirements.in.
«Горячая» установка
Сравнительный анализ установки пакета (команда uv sync) с использованием «теплого» кэша. Эквивалентно удалению и повторному созданию виртуальной среды, а затем заполнению ее зависимостями, которые были раньше установлены на том же компьютере.

На графике видно, что UV в разы обгоняет своих конкурентов — PDM, Poetry и pip-sync. Poetry занимает второе место.
«Холодная» установка
Анализ установки пакетов с использованием «холодного» кэша. Равно выполнению команды uv sync на новом компьютере или в CI (предполагается, что кэш менеджера пакетов — не общий для всех запусков).

UV занимает первое место по скорости выполнения, но отставание других пакетных менеджеров намного меньше, чем в тесте выше.
«Теплое» разрешение зависимостей
Тест на разрешение зависимостей (uv lock) с помощью «теплого» кэша, но без существующего файла блокировки (uv.lock). Равнозначно удалению requirements.txt для его генерации из файла requirements.in.

Тут и нечего говорить: UV лидирует.
«Холодное» разрешение зависимостей
Сравнение разрешения зависимостей с помощью холодного кэша. Соответствует запуску uv lock на новом компьютере или в CI — при условии, что кэш менеджера пакетов не используется совместно для всех запусков.

UV справился менее чем за 0,5 секунды, когда его коллеги по цеху — за 3 и более секунд.
Что в итоге
Подытожим сравнительной таблицей:
| Параметр | Poetry | Uv | 
| Год появления | 2018 | 2024 | 
| Версия Python | 3.9-3.13 | 3.8-3.13 | 
| Текущий релиз | 2.0.1 | 0.5.25 | 
| Лицензия | MIT | Apache-2.0 или MIT | 
| ЯП проекта | Python | Rust | 
| Кол-во контрибьюторов | 581 | 304 | 
| Кол-во звезд | 32,5 тыс. | 37,6 тыс. | 
Первое, что бросается в глаза, — это скорость работы UV. Кто бы что ни говорил, он все равно очень быстрый. Благодарить можно как разработчиков, так и то, что проект написан на Rust. Только в одном тест-кейсе, когда проводилась «холодная» установка, Poetry приближался к UV. В остальных случаях UV — безусловный лидер.
Как и в прошлом моем посте про сравнение FastAPI и Litestar, важно подчеркнуть различие версий у Poetry и UV. Первый проект начал разрабатываться в далеком 2018 году, и текущий релиз начинается с 2.0 — это говорит о стабильности продукта. UV появился в 2024 и до сих пор движется к первому крупному релизу. Пока же его версия 0.5 — а это не гарантирует бесперебойной работы в продакшне.
UV дополнительно поддерживает версию Python 3.8. Пункт может быть важен для команд, которые сейчас разрабатывают решения на этой версии языка программирования.
Лицензия проекта Poetry — MIT. У UV ее можно выбрать — MIT или Apache-2.0.
Инициализация проекта при помощи Poetry более user-friendly и позволяет сразу указать описание проекта, его авторов, поддерживаемые версии Python и лицензию. В этом плане UV более минималистичен, но приходится вручную открывать и редактировать pyproject.toml.
Кто уже использует UV в проде, поделитесь своим полетом в комментариях. Пишите, какой менеджер пакетов используете вы — посмотрим, что на Хабре популярнее.
Что еще почитать:
Комментарии (14)
 - r2d18.02.2025 13:12- Автор, а вы можете сказать почему в кинотеатре где вы занимаетесь бэкендом нет обычных фильтров что бы можно было отфильтровать фильмы по жанру\году\стране? 
 - f1ex018.02.2025 13:12- poetry, uv всё это надстройки без которых можно обходиться. ориентироваться лучше на PEP 518 и PEP 621. у poetry есть существенный недостаток, он еще далек о стабильной версии и не стоит удивляться если после обновления у вас станут возникать ошибки. - По UV из статьи не понять как собирается пакет. - В целом статья с пробелами, да тема выбрана из разряда, есть плохое решение и еще одно, попробуем их сравнить по непонятным метрикам. Автору стоила заглянуть в исходники какой-либо библиотеки более или менее популярной (например fastapi, flask, numpy и т.д.), удивиться что там нет ни poetry, ни uv, изучить используемые технологии и написать хорошую статью.  - kivsiak18.02.2025 13:12- https://github.com/fastapi/fastapi/blob/master/.github/workflows/test.yml 
 И uv и ruff в наличии, uv - это не сборщик. по крайней мере пока.
 Flask уже давно не передовой с точки зрения прогресса продукт.
 Numpy слишком тяжелый и специфичный проект и uv им последнюю очередь нужен.
 И нет, без uv я уже жить не хочу. Это наверно лучше что было сделано для тулинга питона за последние несколько лет
 Сделают еще тайпчекер внутри ruff я еще и pyright выкину. - f1ex018.02.2025 13:12- https://github.com/fastapi/fastapi/blob/master/pyproject.toml - build-backend = "pdm.backend" 
 
  - RH21518.02.2025 13:12- он еще далек о стабильной версии - У меня большие вопросы к инструменту, который достиг второй версии, но никак не может стабилизироваться. 
 
 
           
 
CrazyOpossum
Всегда против тулз на языках, не совпадающих с целевым. Цикл отладки размыкается и разработчик лишается мгновенной обратной связи. Скорость для пакетного менеджера имеет значение только в CI/CD, это как раз горячая установка в которой отставание незначительно, и вряд ли является решающим тормозом в пайплайне. С другой стороны, разработчики на Rust не заинтересованы кровно в надёжности тулзы для разработчиков на Python, в отличие от poetry.
RH215
Никакого разделения на "разработчиков на Rust" и "разработчиков на Python" тут нет. Есть разработчики на Python и Rust. Python вообще никогда не был замкнутой на себе экосистемой.
kompilainenn2
а что там насчет NumPy и еще кучи питоновых либ, написанных на С?
CrazyOpossum
Это не тулзы. Я говорю про проекты, которые применимы сами к себе - тестовые фреймворки, линтеры, стайлеры и, да, пакетные менеджеры.
Roman_Cherkasov
У нас довольно большой проект десктопного приложения, который разбит на микросервисы (это позволяет нам разрабатывать модули и обновлять их независимо друг от друга). Изначально это был монолит, который мы успешно попилили. В процессе перехали с `pip install -r ...` на poetry. Пока модулей было 3-4 - все было нормально. Когда модулей стало 20+ резолв зависимостей время от времени начал занимать какое-то не адекватное количество времени. У нас в чате скидывали скрины с 3000+ секунд, на выполнение poetry update.
Мы некоторое время искали проблемы внутри (и они определенно были. Например бинарные файлы в репах). Исправили это. Но время на poetry update для проекта в который подключены все модули - 500-600 секунд запросто.
В тестовом формате добавили uv. Первый резолв долгий, около 120-150 секунд. Но дальше все стало сильно лучше 20-30 секунд и обновления уже загружены. И о чудо. Добавление конкретной ревизии модуля (по имени ветки или хэшу коммита) не растягивает общий резолв. Короче команда радуется, а я все ещё настороженно отношусь к продуктам с нулевой мажорной версией.
С CI\CD кстати в poetry не так больно, и разницы с uv - нет. Так как уже сформирован lock файл. Нет необходимости решать зависимости, просто берешь пакеты и устанавливаешь.
CrazyOpossum
У вас poetry update частая операция? Я тоже над немаленьким проектом работаю, но мы обновляем зависимости только по веским причинам и редко сразу несколько:
poetry lock --no-updateреагирует только на изменённые в pyproject.toml версии.Roman_Cherkasov
У разработчиков не прям чтобы частая, но вот тестеровщики - очень даже, потому что им надо тестировать модули в составе продуктов.
Roman_Cherkasov
Ещё раз обращаю внимание, что это не резолв внешних зависимостей, это модули нашего приложения. Внешние зависимости у нас тоже с фиксированными версиями и обновляются только при CVE или других критичных багфиксах
kalombo
Любой инструмент либо вызывает боль на данный момент, либо нет. Если вам норм с poetry/pip, то переходить на uv нет смысла. Если у вас есть проблемы с uv, а pip/poetry их решает, то есть смысл перейти на pip/poetry. А все эти домыслы про то, что uv испортится в будущем(потому что на расте, потому делается сторонней фирмой и т.п.) точно также применимы и к poetry и к pip, pip по сути уже "испортился". Мы не знаем, что будет завтра, возможно pip переделают и он станет самым лучшим менджером в python. Свитчится придётся всё равно рано или поздно, т.к. мир меняется и появляются новые инструменты, которые вытесняют старые.