uv, poetry, pip-tools
pip — стандарт для установки пакетов с 2008 года. Он работает, его все знают. Но он медленный, и его dependency resolver всё ещё временами выдаёт сюрпризы. С 2020-х появилась волна альтернатив: poetry, pdm, pip-tools, и финальный игрок — uv от Astral (создатели ruff).
В мае 2026 uv стал стандартом для нового Python-DE проекта. Этот урок: чем он отличается от pip, как использовать в Dockerfile, когда стоит остаться на poetry, что такое lock-файлы.
Почему pip медленный
Pip написан на чистом Python. Что делает при pip install pandas:
- Резолвит зависимости: дергает API PyPI для каждого пакета, читает manifest, разбирается с version constraints.
- Скачивает wheels.
- Распаковывает в site-packages.
- Запускает install hooks (если есть).
Самый медленный шаг — резолюция. На проекте с 30 транзитивными зависимостями pip может тратить 10-20 секунд только на «думанье».
Что такое Linux: ядро, GNU и system calls
uv: Rust-implementation
uv — реализация pip и pip-tools на Rust, от Astral. Совместима с pip CLI, но в 10-100 раз быстрее на типичных операциях.
Установка:
# macOS
brew install uv
# Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Через pip (если уже есть Python)
pip install uv
Использование как drop-in replacement для pip:
uv pip install pandas
# то же что pip install pandas, но за 0.5 сек вместо 4 сек
uv pip install -r requirements.txt
# то же что pip install -r requirements.txt
Бенчмарки от Astral (на проекте django + 40 зависимостей):
pip install— 30 секунд.uv pip install— 3 секунды.
Это 10x. Для проекта с pandas + scipy + sklearn — ещё больше (50-100x на cold-cache).
uv в Dockerfile
Простой вариант:
FROM python:3.13-slim
RUN pip install --no-cache-dir uv
WORKDIR /app
COPY requirements.txt .
RUN uv pip install --system -r requirements.txt
COPY . .
CMD ["python", "main.py"]
--system важен: uv по умолчанию ставит в virtualenv. --system означает «ставь в глобальный Python» — это то, что мы хотим в Docker (контейнер сам себе изолирует, virtualenv лишний).
С BuildKit cache (рекомендуется):
# syntax=docker/dockerfile:1.7
FROM python:3.13-slim
# uv напрямую как бинарь (без pip install — быстрее)
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system -r requirements.txt
COPY . .
CMD ["python", "main.py"]
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv — берём готовый бинарь uv из официального registry. Это быстрее pip install uv (нет pip-резолюции, просто copy файла).
Bench: проект с airflow + pandas + 25 зависимостей.
| Подход | Cold build | Hot rebuild (правка кода) |
|---|---|---|
| pip install | 120 сек | 5 сек (layer cache) |
| uv pip install | 15 сек | 5 сек |
| uv + BuildKit cache | 15 сек | 5 сек |
| uv + BuildKit cache (после смены реквайрментов) | 5 сек | n/a |
uv даёт ускорение даже без BuildKit cache.
uv: новый формат проекта (pyproject.toml)
uv поддерживает PEP 621 — стандартный формат pyproject.toml:
[project]
name = "my-etl"
version = "0.1.0"
dependencies = [
"pandas>=2.2",
"sqlalchemy>=2.0",
"psycopg[binary]>=3.2",
]
Команды:
uv venv # создать .venv
uv pip install -e . # установить проект как editable
uv lock # сгенерить uv.lock
uv sync # установить точно из lock
uv.lock — это lock-файл с точными версиями всего дерева зависимостей. Аналог poetry.lock или Cargo.lock. Коммитится в git, гарантирует воспроизводимость.
В Dockerfile:
# syntax=docker/dockerfile:1.7
FROM python:3.13-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project
COPY . .
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen
CMD [".venv/bin/python", "main.py"]
--frozen запрещает обновление lock-файла (если рассинхрон — fail). --no-install-project ставит только зависимости, не сам проект (это для layer cache: deps отдельно от кода).
Poetry
poetry — другой популярный менеджер, появился в 2018, написан на Python. Сильные стороны: красивый CLI, хорошие defaults, build-system’ы интегрированные. Слабые: медленнее uv, иногда странные edge cases в резолверке.
В Dockerfile с poetry:
FROM python:3.13-slim AS builder
RUN pip install poetry==1.8.0
WORKDIR /app
COPY pyproject.toml poetry.lock ./
RUN poetry config virtualenvs.create false \
&& poetry install --no-root --only main
COPY . .
CMD ["python", "main.py"]
virtualenvs.create false — поставить в системный Python (как uv --system).
В 2026 года тренд — poetry export -f requirements.txt для извлечения requirements.txt, а дальше уже pip / uv. Это позволяет использовать poetry для управления и lock’ом, а в Docker — быстрый uv:
# На dev-машине
poetry add pandas
poetry export -f requirements.txt --output requirements.txt
git commit -am "Add pandas"
# В Dockerfile
FROM python:3.13-slim
COPY requirements.txt .
RUN uv pip install --system -r requirements.txt
pip-tools (pip-compile)
pip-tools — старшая школа: deterministic lock-файл из requirements.in. requirements.in пишешь руками, pip-compile генерит requirements.txt с pinned версиями.
requirements.in:
pandas>=2.2
sqlalchemy>=2.0
psycopg[binary]
pip install pip-tools
pip-compile requirements.in
# Генерит requirements.txt с точными версиями + хешами
# Обновить:
pip-compile --upgrade requirements.in
requirements.txt после:
pandas==2.2.3
# via -r requirements.in
sqlalchemy==2.0.36
# via -r requirements.in
psycopg==3.2.3
# via -r requirements.in
...
В Dockerfile — обычный pip install -r requirements.txt. Простой и понятный паттерн, ничего магического.
В 2026 — это устаревающий подход. uv покрывает всё, что делал pip-tools, плюс быстрее.
Что выбрать в 2026
| Инструмент | Кому подходит | Скорость | Когда брать |
|---|---|---|---|
| pip | всем (default) | медленно | Legacy, простые проекты |
| pip-tools | командам с requirements.in | средне | Если уже используется |
| poetry | командам с pyproject.toml + lock | медленно | Если уже используется |
| uv | новые проекты | очень быстро | DEFAULT для нового DE-проекта |
Для нового Junior-DE проекта в 2026 — uv. Он:
- В 10-100x быстрее pip — экономит часы CI-времени в год.
- pip-совместимый CLI — знание pip не пропадает.
- Поддерживает pyproject.toml + lock.
- Активно развивается, backed by Astral (ruff team).
Реальный bench
Проект: airflow + pandas + sqlalchemy + dbt-postgres + 30 транзитивных deps.
# Чистая сборка, BuildKit cache очищен
# Вариант A: pip
docker build -f Dockerfile.pip --no-cache -t bench-pip .
# 145 сек
# Вариант B: uv (без BuildKit cache)
docker build -f Dockerfile.uv --no-cache -t bench-uv .
# 22 сек
# Вариант C: uv + BuildKit cache
docker build -f Dockerfile.uv-cache --no-cache -t bench-uv-cache .
# 18 сек
# Ребилд после добавления одной зависимости:
# pip — 80 сек (тянет всё заново)
# uv — 5 сек (incremental)
uv даёт ~8x ускорение на cold build. В CI это разница между «PR ждёт 3 минуты сборки» и «PR ждёт 25 секунд».
Pitfall: native deps
uv ускоряет резолюцию и скачивание, но не сборку из исходников. Если для какого-то пакета нет wheel под твою платформу — uv будет вызывать pip-build, и компиляция займёт те же минуты, что и с pip.
# Если pandas нет wheel — фигня будет с любым менеджером
FROM python:3.13-alpine
RUN uv pip install --system pandas
# Будет компилировать минут 5
Решение: использовать slim-base (где manylinux wheels работают) и не лезть в edge cases.
Попробуй сам
- Установи uv:
brew install uvилиpip install uv. Проверь:uv --version. - Создай простой проект, requirements.txt:
pandas sqlalchemy psycopg[binary] - Сравни время
pip install -r requirements.txtиuv pip install -r requirements.txtлокально. - Собери два Dockerfile (один pip, один uv), замерь время:
Запиши разницу.time docker build --no-cache -f Dockerfile.pip -t pip-test . time docker build --no-cache -f Dockerfile.uv -t uv-test . - Добавь BuildKit cache к uv-варианту. Снова замерь cold build. Должно стать ещё чуть быстрее (за счёт ещё-более-эффективного uv cache).
- Бонус: используй
pyproject.toml+uv.lockвариант.uv lockсоздаст lock-файл.uv sync --frozenв Dockerfile.