RTP DesportoBenfica e AC Milan marcam encontro na Liga EuropaCNN TürkAK Parti Milletvekili Mehmet Muharrem Kasapoğlu: Çocukların futbol sevgisi Rum kesimine tehdit değil!ESPN'That dream is done': USMNT's Richards puts World Cup heartbreak behind himוואלהכביש 443 נחסם: בעקבות מעצר בחור ישיבה - צפי למהומות באזורDaily MaverickState property register essential to cutting wasteful government leasesThe Jerusalem PostParashat Ki Tavo: The finest generationInquirerManila Water advances complete water cycle management with September desludgingScreen RantHalo: The Prophet’s Hand Takes Players Back To The Fall Of ReachColliderAlan Ritchson's Biggest Action Movie Since 'War Machine' Officially Makes Digital DebutThe RegisterCISA: Most exploited vulnerabilities should have been eradicated decades agoIl Fatto Quotidiano“Se porto della sostanze stupefacenti in aeroporto posso incontrarlo?”: tutti pazzi per Bolt, il cane antidroga che ha conquistato il webХабрПодмена страницы интернет-банка First Partner Bank на Standoff 365
The Daily Newsstand · Free, Always
Friday, August 28, 2026

Мы списали uv со счетов. А потом он ускорил наш CI на 80%

Translate

Всем привет! Меня зовут Артем Целин и я Бэкенд-разработчик в компании “Исходный Код”.

В Python-сообществе вокруг uv в последние месяцы много шума: быстрый резолвинг зависимостей, единый инструмент вместо россыпи утилит и обещания заметно ускорить привычный workflow.

Мы решили проверить это на практике и выбрали для эксперимента один из наших микросервисов: Python 3.14, 37 прямых зависимостей, 153 пакета в lock-файле и типичный для корпоративной разработки стек с приватными пакетами и внутренним Nexus.

Ожидания были простые. Если uv действительно настолько быстрее Poetry, миграция быстро себя окупит.

Результат оказался неожиданным.

На локальной машине uv действительно заметно быстрее резолвил зависимости и генерировал lock-файл. Но как только дело доходило до установки зависимостей по уже готовому lock-файлу, преимущество исчезало, а иногда Poetry оказывался даже быстрее.

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

Мы завершили эксперимент. Через несколько недель к этому вопросу пришлось вернуться из-за алерта от сканера уязвимостей Trivy.

Локальный бенчмарк и первое разочарование

Для первого теста был выбран локальный сценарий, максимально приближенный к обычной разработке: несколько прогонов подряд, перед каждым запуском удаляли виртуальное окружение и очищали кеши pip, Poetry и uv, чтобы каждый прогон начинался с нуля.

Сравнивали два отдельных сценария для каждого инструмента:

  • Генерация lock-файла (poetry lock / uv lock)

  • Установка по уже готовому lock-файлу (poetry install / uv sync)

Картина получилась неоднозначной.

В части резолвинга uv действительно подтвердил свою репутацию, создавая lock-файл заметно быстрее Poetry.

В сценарии, который для команды важнее всего в ежедневной работе (установка зависимостей по уже закоммиченному lock-файлу), преимущество исчезало.

По результатам тридцати прогонов с использованием Poetry 1.7.1 и uv 0.11.8 средняя картина выглядела так:

Сценарий

Poetry

uv

Генерация lock-файла

25 с

16 с

Установка по готовому lock-файлу

7 с

13 с

uv побеждал в генерации lock-файла, которая происходит реже. Poetry показывал себя лучше в более частом сценарии: установке по уже готовому lock-файлу.

Почему uv так медленно устанавливал пакеты в этом конкретном окружении, мы не исследовали глубоко.

Результат стабильно воспроизводился на нашей локальной сети и в нашем окружении. Делать выводы о внутренних причинах поведения сетевого стека без отдельного профилирования было бы спекуляцией.

Практический вывод был простым: uv быстрее резолвит зависимости. Поскольку наша команда коммитит lock-файл в репозиторий и большую часть времени работает уже с готовым графом зависимостей, эта разница в скорости почти не ощущалась.

Миграция не выглядела оправданной, поэтому мы завершили эксперимент и остались на Poetry.

Trivy не оставил нам выбора

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

В пайплайнах мы используем Trivy для проверки зависимостей на уязвимости. В какой-то момент стало понятно, что оставаться на Poetry 1.7.1 дальше нельзя.

Проблема была не в нашем коде, а в собственных транзитивных зависимостях Poetry и связанных с ним компонентах. Trivy начал стабильно подсвечивать проблемы безопасности, нарушавшие наши внутренние регламенты.

Обновление до Poetry 2.x из задачи с низким приоритетом превратилось в срочную необходимость.

И вот здесь начались действительно неприятные сюрпризы.

Сам по себе Poetry 2 работал нормально, но изменилась логика работы с источниками пакетов.

В CI у нас используется внутренний Nexus и приватные пакеты из корпоративного GitLab, поэтому в pyproject.toml пришлось добавить описание этих репозиториев:

Ini, TOML

[[tool.poetry.source]]
name = "company-nexus"
url = "
https://nexus.example.com/repository/pypi/simple"
priority
= "primary"

Эта настройка имела смысл для CI, где пайплайнам нужны явные объявления источников для внутренних пакетов.

Добавление [[tool.poetry.source]] привело к тому, что Poetry стал обращаться к этим внутренним индексам при каждой операции lock и install, в том числе при локальной разработке.

Обычные локальные команды вроде poetry lock или poetry install начали делать сетевые запросы во внутренний Nexus прямо во время повседневной работы.

Это создало организационные сложности:

  • Разработчики не всегда были подключены к корпоративному VPN.

  • Внутренний DNS по умолчанию был доступен не на всех локальных машинах.

Локальная разработка внезапно стала требовать постоянно включенного корпоративного VPN.

Главный вопрос состоял уже не в том, быстрее ли uv, а в том, что привычный процесс работы с Poetry перестал быть удобным.

Временное решение: свой парсер poetry.lock

Нам не хотелось сразу менять весь стек.

Poetry все еще был удобен для локальной работы при условии, что мы сможем обойти проблему с внутренними репозиториями в CI. Мы попробовали устранить ограничение без полной миграции.

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

Для этого требовалось только одно: научиться превращать poetry.lock в обычный requirements.txt.

Готового инструмента под наши требования не нашлось. Команды вроде poetry export все равно требовали Poetry и тащили за собой те же транзитивные зависимости, на которые ругался Trivy. Я написал небольшой скрипт-парсер для этого преобразования.

Схема работы выглядела так:

  1. Разработчики продолжают работать локально через Poetry.

  2. Обновленный poetry.lock коммитится в репозиторий.

  3. На стейджинге скрипт преобразует lock-файл в requirements.txt.

  4. Зависимости устанавливаются через стандартный pip install.

На бумаге схема выглядела надежно.

Она сохраняла привычную локальную разработку, убирала алерты Trivy на транзитивные зависимости Poetry, выводила Poetry из пайплайна развертывания и обходила проблемы с обращением к первичным источникам.

Однако самописный парсер добавлял накладные расходы.

Перед каждым запуском пайплайна системе приходилось:

  • Распарсить формат lock-файла.

  • Сгенерировать корректный requirements.txt.

  • Проверить совместимость формата.

  • Поддерживать код парсера на случай будущих изменений в структуре lock-файла.

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

Выполнение оказалось медленнее, чем хотелось. Время уходило на генерацию requirements.txt, а затем на этап установки через pip.

Решение ощущалось как временный костыль, а не постоянная стратегия. Это заставило нас снова оценить uv как быстрый установщик для CI-пайплайнов.

Второй шанс для uv

Когда мы вернулись к uv, наша цель изменилась.

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

Теперь задача стала конкретной и прагматичной: может ли uv просто быстрее ставить пакеты в пайплайне?

Мы сознательно не меняли сам сценарий пайплайна. Набор устанавливаемых зависимостей, порядок выполнения, этапы пайплайна и группы зависимостей остались точно такими же, как в версии с Poetry.

Мы обновили только слой подготовки окружения, заменив вызовы Poetry на uv sync.

Мы встроили uv на стейджинг через легкий bootstrap-скрипт и отдельный шаг синхронизации:


Bash

. ./tools/bootstrap_uv.sh && ./tools/uv_sync.sh

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

Bash

. ./tools/bootstrap_uv.sh && ./tools/uv_sync.sh --only-group linters

Затем выполнялись стандартные шаги проверки:

  • ruff format и ruff check

  • mypy

  • pytest

  • Проверки Sonar

  • Сканирование безопасности Trivy

Время выполнения существенно сократилось.

Мы прогнали по 30 запусков пайплайна для обоих вариантов и сравнили полное время работы всех этапов.

Средние результаты по времени:

Инструмент

Среднее время пайплайна

Poetry 1.7.1

5 мин 10 с

uv 0.11.8

2 мин 50 с

Общее время выполнения пайплайна сократилось примерно на 45% (с 5 минут 10 секунд до 2 минут 50 секунд), что означает прирост эффективности выполнения на 80%.

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

Причина была очевидной.

При локальном тестировании мы запускали uv в условиях нестабильного доступа к внешним индексам и сравнивали его с оптимизированным Poetry.

В CI доступ по сети к внутреннему Nexus был быстрым и стабильным, что позволило реализации uv на Rust проявить себя в полной мере.

Наша первоначальная оценка практической пользы uv была преждевременной.

Полный переход на uv

После результатов в CI стало понятно, что первое впечатление от uv исказили условия локального тестирования.

Сначала uv казался непривычным из-за другого синтаксиса команд, измененной конфигурации pyproject.toml и иной модели работы с зависимостями по сравнению с Poetry.

Например, команда uv sync выглядела непривычно, так как Poetry разделяет генерацию lock-файла и установку зависимостей на разные команды, тогда как uv выполняет их за один шаг.

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

Использование двух инструментов означало бы поддержку параллельных схем:

  • Poetry для локальной разработки

  • uv для CI-пайплайнов

Такой подход требовал:

  • Поддерживать два набора инструкций к проекту.

  • Отслеживать два набора команд.

  • Управлять возможными расхождениями между локальной средой и CI.

Эта сложность была лишней.

Если uv надежно работал в CI, продолжать использовать Poetry локально только из привычки не имело смысла.

Мы перевели локальную разработку на uv. Это решило и проблему с VPN: локально uv забирает пакеты напрямую из публичных реестров без постоянного подключения к корпоративному VPN, избегая обращения к первичным источникам, как в Poetry 2.

Адаптация к uv прошла гладко, как только мы перестали сравнивать каждую команду напрямую с Poetry.

Теперь проект использует единый подход к управлению зависимостями, гарантирующий одинаковое поведение окружения локально и в CI.

Выводы

Наш переход проходил по следующим шагам:

  1. Протестировали uv локально.

  2. Не увидели достаточного выигрыша локально и остановили миграцию.

  3. Уперлись в ограничения безопасности и конфигурации Poetry 2.

  4. Сделали временный обходной скрипт для poetry.lock.

  5. Повторно протестировали uv целевым образом внутри CI-пайплайнов.

  6. Заметно сократили время выполнения пайплайна.

  7. Стандартизировали uv для локальной среды и CI.

Если бы мы остановились на первом бенчмарке, мы бы остались на Poetry и полностью пропустили uv.

Когда инструмент дошёл до реальной эксплуатации, выигрыш проявился совсем не там, где мы его искали на старте.

Если инженерный инструмент не дает ожидаемого эффекта с первой проверки - это еще не значит, что он не работает. Часто сценарий теста просто не попал в настоящее узкое место процесса.

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.