Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Идеальный тулинг для управления зависимостями в python проектах

Идеальный тулинг для управления зависимостями в python проектах

Сравним весь тулинг для контроля зависимостей в Python (а его уже очень много) по множеству критериев и попытаемся выбрать лучшие инструменты для задач современного бекенда. Обсудим будущее этих утилит, разные PEP, историю пакетного менеджмента в питоне. Поделюсь практическим опытом применения такого тулинга для большого количества микросервисов, проблемами, с которыми мы сталкивались. А ещё попытаюсь построить аналитику на будущее, ответив на вопрос «какой тулинг для зависимостей будет лучшим завтра?».

Выступление на МТС true tech day 2024

Denis Anikin

May 18, 2024
Tweet

More Decks by Denis Anikin

Other Decks in Programming

Transcript

  1. Денис Аникин, https://xfenix.ru Техлид/Комьюнити лид в Райфе Идеальный тулинг для

    управления зависимостями в python проектах Development {
  2. Представлюсь — Меня зовут Денис Аникин — Я тех- и

    комьюнити- лид в Райфе — У меня 3 команды в scrum, 1 в less — Я fullstack (async python + микросервисы и typescript + react) — Я иногда выступаю на конференциях и вхожу в ПК http://xfenix.ru
  3. О чём доклад — Я (вы) пишу микросервисы — Мне

    надо в них отслеживать все зависимости — Для этого нужны инструменты. Мы их рассмотрим, сравним и выберем лучшие
  4. История тулинга (1) божественное ничего 1989 — 2004 easy_install +

    egg virtualenv (где-то) 2004 — pip 2008 — pypa & virtualenv 2011 — wheel 2013 —
  5. А что не устраивает в pip + virtualenv? — Изоляция

    есть — Средство доставки тоже — Переносимость обеспечивается requirements.txt
  6. Или по-другому: — «Да ладно, у нас такого не было,

    лол :)» — «А у меня никогда не случалось!» — «Ни разу не видел» — «Какая-то надуманная проблема» — Когда столкнулись: «ой, я хотел месяц иначе потратить :(»
  7. Но для начала маленькая справка — PEP 508 (формат зависимостей)

    — PEP 517 (формат для source trees) — PEP 518 (минимальные требования к системе сборки) — PEP 621 («содержимое pyproject») — https://packaging.python.org/en/latest/specifications/pyproject-toml/#pyproject-toml-spec — https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-requires-dist — И еще немного: 725, 735, 660, 631, 633
  8. Окей, мы откроем METADATA в wheel Requires-Dist: starlette<0.38.0,>=0.37.2 Requires-Dist: pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4

    Requires-Dist: typing-extensions>=4.8.0 Requires-Dist: fastapi-cli>=0.0.2 Requires-Dist: httpx>=0.23.0 Requires-Dist: jinja2>=2.11.2 Requires-Dist: python-multipart>=0.0.7 Requires-Dist: ujson!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,>=4.0.1 Requires-Dist: orjson>=3.2.1 Requires-Dist: email_validator>=2.0.0 Requires-Dist: uvicorn[standard]>=0.12.0 Requires-Dist: httpx>=0.23.0; extra == "all" Requires-Dist: jinja2>=2.11.2; extra == "all" Requires-Dist: python-multipart>=0.0.7; extra == "all" …
  9. Окей, мы откроем METADATA в wheel Requires-Dist: starlette<0.38.0,>=0.37.2 Requires-Dist: pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4

    Requires-Dist: typing-extensions>=4.8.0 Requires-Dist: fastapi-cli>=0.0.2 Requires-Dist: httpx>=0.23.0 Requires-Dist: jinja2>=2.11.2 Requires-Dist: python-multipart>=0.0.7 Requires-Dist: ujson!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,>=4.0.1 Requires-Dist: orjson>=3.2.1 Requires-Dist: email_validator>=2.0.0 Requires-Dist: uvicorn[standard]>=0.12.0 Requires-Dist: httpx>=0.23.0; extra == "all" Requires-Dist: jinja2>=2.11.2; extra == "all" Requires-Dist: python-multipart>=0.0.7; extra == "all" …
  10. Не заметите — «Минорное» изменение может приводить к серьезным проблемам.

    История из жизни: изменился lxml совсем чуть-чуть, а это «положило» селекторы в scrapy. Дебаг съел много нервных сил и времени — Тесты могут не показать (не все тесты идеальны) — Проблема «протяжена» во времени — Сложно дебажить (и неприятно) — Вы давите на классическую проблему «у нас не воспроизводится»
  11. Собираем вместе — Зависимость зависимости может измениться незаметно — Вам

    ОЧЕНЬ надо постараться, чтобы понять от чего зависит ваша зависимость — Против вас pypi.org, pyproject.toml и PEPы (вы не изучите и не запомните) — У зависимости зависимости тоже есть зависимость…
  12. Всё вместе — Человеческие ошибки (тулинг pip + requirements.txt предполагает

    ручную работу) — Нет уверенности, что пакет не подменят в одном из репозиториев (после того как вы его установили). Некоторые гарантии даёт pypi, но не все другие репозитории… — Разрешение конфликтов — Фиксирование зависимостей несет в себе ещё один букет проблем
  13. Фиксирование зависимостей — Вариант 1: пишем зависимости проекта в reqs.txt

    + фиксируем версии — Вариант 2: pip freeze > reqs.txt — Вариант 3: вариант 1 + задаём версии гибко — Вариант 4: вариант 1 + не указываем версии вообще
  14. Для начала важное — Я очень давно не использую venv

    + reqs.txt + pip — И вам не советую — Почему мы уже определились, а теперь поговорим про тулинг зависимостей
  15. Ответ простой (относительно) — Надо использовать так называемые «lock» файлы

    — Кто изобрел их первым не ясно (apt, rpm? ранее?) — Популярность они получили благодаря npm
  16. Что-то такое { "name": "my-project", "lockfileVersion": 1, "requires": { "dependency1":

    "^2.3.1", }, "dependencies": { "dependency1": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/dependency1/-/dependency1-2.3.4.tgz", "integrity": "sha512-abc123def...", "requires": { "subdependency1": "^1.2.0" } } } }
  17. Что-то такое { "name": "my-project", "lockfileVersion": 1, "requires": { "dependency1":

    "^2.3.1", }, "dependencies": { "dependency1": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/dependency1/-/dependency1-2.3.4.tgz", "integrity": "sha512-abc123def...", "requires": { "subdependency1": "^1.2.0" } } } }
  18. И конечно python версия (toml) лок файла [[package]] name =

    "babel" version = "2.14.0" requires_python = ">=3.7" summary = "Internationalization utilities" groups = ["doc"] dependencies = [ "pytz>=2015.7; python_version < \"3.9\"", ] files = [ {file = "Babel-2.14.0-py3-none-any.whl" , hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287" }, {file = "Babel-2.14.0.tar.gz" , hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363" }, ]
  19. Pipenv — Первый тул, который давал комплексное управление всем процессом

    — Убирает фактор человека, давая 2 файла: Pipfile, Pipfile.lock — Мы получаем: создание виртуальных окружений автоматом, установку и контроль зависимостей, повторимость сборок, исключение человеческого фактора
  20. Сегодня я использовать pipenv не стану — Pipfile это какая-то

    полу-функциональная редакция pyproject, она не входит в стандарт — У pipenv были больше пробелы в истории развития — Следующие утилиты делают pipenv не очень-то нужным (на мой взгляд)
  21. Poetry — Использует pyproject.toml (почти* в согласии со стандартом) —

    Как и pipenv он использует pip под капотом, но у него более комплексный и умный резолвер зависимостей — В добавок ко всем бонусам pipenv мы получаем ещё и возможность с помощью наличия всего-лишь одного pyproject.toml собирать и даже паблишить собственные пакеты! — Приятный CLI с подсветкой
  22. Бывало такое (на практике) — С 1.1 на 1.4 было

    много проблем — https://github.com/python-poetry/poetry/issues/6300 — https://github.com/python-poetry/poetry/issues/7170 — https://github.com/python-poetry/poetry/issues/4242
  23. Претензии к poetry — Не всегда понятный фидбек по ошибкам

    — Немного замученный poetry config (однажды я 4 часа ковырялся в keyring потому, что poetry никак не показывает, что доступ к закрытому репозиторию сейчас доступен через keychain) — Не полное следование pyproject: в PEP 621 определена секция [project] и dependencies ключ, poetry использует [tool.poetry] вместо них
  24. PDM

  25. Большие плюсы PDM ✅ — в отличие от poetry следует

    PEP 621 (те самые секции [project] & dependencies) ✅ — имеет централизованый кеш похожий на pnpm (причем, с хард и софт линкингом!) ✅ — имеет свой resolver & downloader, не полагаясь на pip (вроде это даже быстрее работает, чем у конкурентов) ✅❌ — поддерживает __pypackages__, он же PEP 582
  26. Неожиданный поворот — PEP 582 опционален. По-умолчанию PDM использует virtualenv

    — PDM теперь позволяет использовать сборку и паблишинг пакетов! — Вы можете управлять версиями python через него…
  27. Огрмный респект авторам — Вся причина существования PDM — это

    __pypackages__ — Они не стали цепляться за прошлое и убрали эту функциональность под опцию — Они поняли, что нужна сборка пакетов — Они поняли, что нужен контроль питон версий — Они сделали совместимость с rye
  28. Как я объясняю себе — Для тех, кто ненавидит всё

    остальное — Для тех, кто по какой-то причине влюблен в pip
  29. UV

  30. UV — Разработка создателей ruff — Быстрее pip, poetry, pdm,

    pip sync в 10-100х раз (а вы сомневались?) — Имеет свой глобальный кеш — Умеет переопределять стратегии определения зависимостей — Можно переопределить зависимости пакета (<< вот это крутая фишка!)
  31. Точно плюсы uv ✅✅✅ — глобальный кеш ✅✅✅ — переопределение

    зависимостей (это может быть очень полезным) ✅✅✅ — скорость (https://github.com/astral-sh/uv/blob/main/BENCHMARKS.md вот тут бенчмарки не особо врут; личный опыт использования — крайне позитивен)
  32. Вроде бы — Амбиции как у pdm & rye —

    Умеет похожее (версии питона, сборка пакетов, зависимости) — Есть интересные особенности: fmt, генерация шаблонов — Но, например, нет нормального CLI управления зависимостями (они ставятся on-demand)
  33. На мой взгляд, hatch больше про сборку пакетов, чем про

    управление зависимостями в сервисах
  34. Rye

  35. Плюсы rye — Под капотом у него uv (и pip

    sync) — Он умеет паблишить и билдить пакеты (через build & twine) — Он умеет отслеживать зависимости и делать лок файлы — Следует PEP 621 — Он управляет версиями python и умеет их ставить — Можно ставить глобально утилиты и управлять ими (например, ruff) — У него есть fmt (!!!)
  36. Так почему мы не используем rye? — Сы-ро-ва-то — Документация

    не слишком дружелюбна. Чтобы понять как управлять версиями python вам понадобится отправиться в toolchain и на ютуб
  37. Это просто важно проговорить 1) Опыт эксплуатации 2) Прямое сравнение

    3) Рекомендации PYPA (они немного не поспевают за трендами, но всё таки)
  38. Я не фанат итогов, но — Текущий вариант всё-в-одном: pdm

    — Базовый pip можно заменять на uv — А ещё стоит следить за «приемником» pdm & poetry: rye
  39. Экосистема python в 2024 году… Pypy, mypy, mypyc, gopy, pypa,

    pypi, pip, pip-tools, pip-compile, pip-sync, micropipenv, pep, pipx, pipenv, pipfile, pyproject, numpy, scipy, cpython, lpython, cython, brython, cythonize, pyston, peachpy, safepy, pytype, pyodide