Pull to refresh

Comments 24

Кажется, в пункте 2 опечатка в первой команде. Должно быть $ poetry export -f requirements.txt --output requirements.pip?

Это же имя файла для вывода, можно задать любое

Да, но в статье дальше оно используется в следующей команде.

В рекомендациях подразумевается, что твои изначальные зависимости лежат в файле requirements.pip (смотри пункт 1). Далее когда ты уже перенес зависимости в Poetry я предлагаю их перепроверить, т.е. выгрузить командой из пункта 2. После этого получится два файла:

requirements.pip - изначальные зависимости

requirements.txt - то, что находится в Poetry

Другое имя файла в пункте 2 нужно как раз для того, чтобы не перетереть изначальный файл.

-f — это формат вывода, просто он выглядит как имя файла, а --output — это уже сам файл.

Странно. Вы пиарите бренд. А сами закрыли доступ для граждан России.

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

По поводу создание venv.
Не пробовали делать multistage сборку, как раз с созданием venv и переносом его в финальный образ?
Насколько помню, таким образом можно выгадать 100-200мб в размере образа итогового.

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

Можно попробовать копирование, не уверен про 100-200 мб, но точно образ должен быть легче.

По моему опыту просто переносить готовый venv опасно: могут потеряться бинарные зависимости или поехать пути.

Для меня лучше работает такая схема:

  • в базовом образе с помощью Poetry генерируем requirements.txt;

  • там же из requirements.txt собираем wheel-пакеты;

  • монтируем requirements.txt и wheel-пакеты в финальный образ (понадобится DOCKER_BUILDKIT);

  • устанавливаем зависимости из wheel-пакетов обычным pip;

  • PROFIT.

Таким образом в финальном образе получим правильно установленные пакеты, но самих wheel-файлов и даже Poetry там не будет.

переносить готовый venv опасно: могут потеряться бинарные зависимости или поехать пути

согласен, но есть надежда на unit-тесты)

генерируем requirements.txt

изначально хотелось от этого отказаться

Да, это распространенные аргументы в пользу poetry. Хотелось бы их парировать, не холивара ради, но, чтобы обнадёжить тех, кто не хочет или не может отказаться от pip. 

В нашем случае мы не вносили никаких изменений в сам проект, проблему нужно было искать в окружении. Но мы же зафиксировали все версии пакетов? 

Мало кто знает, но штатными средствами легко проверить совместимость Python зависимостей через pip check. Как минимум на уровне грамотного CI это не проблема.  

Ну и в-третьих, версия пакета может не измениться, а содержимое поменяться кардинально. 

Если это реальный вопрос безопасности, эффективнее использовать собственный PyPI индекс. Так вы сможете надёжно проконтролировать содержимое пакетов централизовано, один раз, на все случаи жизни. Следить за тем, чтобы все использовали poetry с проверкой хешей сложнее. 

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

Poetry подразумевает добавление зависимостей только через CLI. Это вызывает трудности если вы пользуетесь виртуализацией, работаете с Python через Docker, например. Со стандартным pip вы можете добавлять зависимости как угодно: руками или средствами вашей IDE.

К тому же автоматизация проще с pip. Например, poetry не умел раньше отдавать версию пакета, а парсить его внутренний формат было гораздо сложнее чем requirements.txt 

Разделение зависимостей на зависимости проекта и зависимости разработки

Иногда скоупы зависимостей могут быть сильно сложнее чем зависимости “проекта” и “разработки”. Например, в наукоёмких проектах у вас могут быть тяжелые, но редко обновляемые ML зависимости, отдельно системные, отдельно проектные, и т.д.

Со стандартным pip это легко разбить на отдельные файлы и контролировать время установки. Например, можно использовать кэширование на уровне Docker чтобы каждый раз не переустанавливать вендорные зависимости. Так не получится сделать с poetry, потому что у него один файл конфигурации. 

Спасибо за коммент! В текущем проекте такой необходимости нет, но на будущее точно будет полезно

Мало кто знает, но штатными средствами легко проверить совместимость Python зависимостей через pip check.

Это не решает все проблемы, из-за которых нужна фиксация зависимостей. Например, в минорной версии может поменяться поведение так как не все следуют SemVer.

В случае pip аналогом скорее была бы команда pip freeze.

Если это реальный вопрос безопасности, эффективнее использовать собственный PyPI индекс. Так вы сможете надёжно проконтролировать содержимое пакетов централизовано, один раз, на все случаи жизни. Следить за тем, чтобы все использовали poetry с проверкой хешей сложнее.

Про свой индекс совет хороший. У нас на работе поднят jFrog Artifactory и это решает много проблем. Но и проблем с тем, чтобы все использовали poetry тоже нет. В CI/CD просто сборка упадёт, если хеши не сойдутся.

Poetry подразумевает добавление зависимостей только через CLI. Это вызывает трудности если вы пользуетесь виртуализацией, работаете с Python через Docker, например. Со стандартным pip вы можете добавлять зависимости как угодно: руками или средствами вашей IDE.

А какие проблемы с Docker? Вроде хорошо всё с контейнеризацией.

Строго говоря, добавлять зависимости можно и правкой pyproject.toml, просто надо будет отдельной командой зафиксировать зависимости. Но и с pip для этого тоже нужна будет команда, так что тут дополнительной сложности нет.

Например, poetry не умел раньше отдавать версию пакета, а парсить его внутренний формат было гораздо сложнее чем requirements.txt

Наоборот, проще же. Это просто TOML, его поддержка скоро в стандартной библиотеке Python будет. Можно загрузить с помощью одной из библиотек и работать как со словарём.

У requirements.txt не такой простой формат. Посмотрите пример из спецификации. Да, есть библиотека, но тогда чем это лучше TOML?

А какие проблемы с Docker? Вроде хорошо всё с контейнеризацией. 

Есть такой подход, вместо venv или локального Python, в процессе разработки использовать "удаленный" Python. В контексте нашего обсуждения это интерпретатор из Docker образа.  

Все зависимости питонячие и системные, включая poetry CLI тогда находятся внутри образа. Значит, чтобы вам обновить pyproject.toml придется вольюмы создавать до хостовых файлов, как-то настраивать команды в своём IDE или через Docker Compose.

Естественно, такая же проблема будет с pip freeze. Я скорее хотел подчеркнуть, что poetry это "CLI-driven" решение, в отличии от pip. Ну или во всяком случае с pip проще работать как с "files-driven" решением.

Сюда же относится проблема с группами зависимостей. Как подсказал alexxxnf выше в poetry можно объявить группы зависимостей, но все они находятся в одном файле pyproject.toml. Это значит что даже если вы распишете установку групп разными шагами в Docker образе, кэш срабатывать не будет. Docker будет определять изменение pyproject.toml и проходить все шаги.

С pip можно разные группы зависимостей оформить в отдельные файлы и юзать кэш Docker по полной. Это вообще не проблема для обычного CRUD API проекта, но если вы работаете с чем-то системным или ML то проблема возникает (пересчёт poetry лок файла или полная установка зависимостей может занимать десятки минут).

Наоборот, проще же. Это просто TOML, его поддержка скоро в стандартной библиотеке Python будет. Можно загрузить с помощью одной из библиотек и работать как со словарём. 

Представьте, у вас какой-то CI или дебаг на продакшене, bash и необходимость узнать версию зависимости. В случае pip это будет обычный греп. В случае poetry может быть описание пакета и его версии в несколько строк, это позволяет TOML формат, обработать это чистым bash будет несколько сложнее. 

Опять же, поддержка poetry в PyCharm появилась год, может два назад. Наверняка в VSCode она тоже есть. Но в каких-то менее распространённых тулах её нет, зато есть pip. 

Если вы решаете задачу обработки в комфортных для себя условиях, конечно, вопрос снимается.

Вообще я не отговариваю использовать Poetry, просто в статье приведены популярные аргументы, основанные на недостатках pip, которые на самом деле неактуальны или возникают из-за неполноты опыта автора.  

Мне, например, нравится Poetry тем, что он пытается юзать и развивать предложенный стандарт проектного файла pyproject.toml, с этим в Python исторически всё не очень, в отличии от других языков.

Есть такой подход, вместо venv или локального Python, в процессе разработки использовать "удаленный" Python. В контексте нашего обсуждения это интерпретатор из Docker образа.

Вы имеете в виду ситуацию, когда запущен контейнер и к нему примонтирована директория с кодом? Так я сам так делаю. Прямо в IDE (VS Code в моем случае) можно открыть терминал и выполнить произвольные команды или автоматизировать нужные действия. Вы, впрочем, это упомянули. Можно вообще настроить обновление lock-файла в pre-commit hooks. Если кто-то забудет обновить lock-файл, это сразу задетектит CI/CD и просто не даст вмерджить PR.

если вы работаете с чем-то системным или ML то проблема возникает (пересчёт poetry лок файла или полная установка зависимостей может занимать десятки минут).

Да, есть такая проблема. Правда, тут не poetry виноват, а тот факт, что для получения списка зависимостей нужно скачать пакет, а, скажем, PyTorch может весить пару гигабайт.

С группами зависимостей проблема тоже есть, тут я согласен. Решать можно по-разному с разной степенью костыльности:

  • Явно устанавливать самый тяжёлый пакет, который точно будет в зависимостях, а потом poetry install. Он не будет качать заново то, что уже установлено. Проблема — версия этого пакета будет в двух местах.

  • В скрипте, который собирает образ, экспортировать группы зависимостей в разные txt-файлы и этим свести задачу к предыдущей.

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

обработать это чистым bash будет несколько слсложнее.

Если есть только bash и grep, то, конечно сложнее. Впрочем, с bash вообще много проблем из-за его очень ограниченных возможностей. Средствами утилит, которые гарантированно предоставлены POSIX, и менее экзотический JSON не разобрать.

Но с другой стороны, в инструментах для CI/CD обычно можно указывать свои образы, а в этом случае ничто не мешает установить любой из конвертеров TOML в JSON и с помощью jq делать запросы произвольной сложности прямо в bash.

Вообще я не отговариваю использовать Poetry, просто в статье приведены популярные аргументы, основанные на недостатках pip, которые на самом деле неактуальны или возникают из-за неполноты опыта автора.

Да, тут, конечно, всё от задач зависит. Я с очень многими вариантами работал. От pip и pip-tools до Bazel (у нас на работе он используется в некоторых проектах даже на чистом Python). И вот лично для себя остановился на Poetry. У него безусловно есть недостатки. Например, невозможность подменить индекс при установке пакетов (приходится экспортировать в requirements.txt) или долгое отсутствие поддержки однофайловых индексов пакетов. Но остальные возможности перекрывают недостатки.

Да, тут, конечно, всё от задач зависит.

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

Спасибо за такой крутой тред :)

Про свой индекс совет хороший. У нас на работе поднят jFrog Artifactory и это решает много проблем. Но и проблем с тем, чтобы все использовали poetry тоже нет. В CI/CD просто сборка упадёт, если хеши не сойдутся.

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

Ну, там альтернатив не так много: ставить из индекса или таскать с собой все зависимости в виде wheel-файлов. Можно, конечно, прямо из корпоративного GitHub ставить, но это тоже сомнительное удовольствие, если в пакете бинарный модуль.

Зато как poetry шикарно и быстро резолвит зависимости. У меня была жуткая связка из зависимостей aws библиотек awscli, boto3 и botocore между собой и другими библиотеками проекта. Версии всего были намертво прописаны в requirements чтобы сборка не занимала часы.

Час расплаты пришёл когда решили переезжать на новую мажорную версию библиотеки которая зависела от более свежих версий boto3.

Ручной подбор не дал результата. Pip env поскрипел пару часов и умер. Poetry справился за 20 минут и с тех пор мои зависимости гладкие и шелковистые. Конечно есть куча странных решений но конкретную задачу управления зависимости poetry решает хорошо

5. Разделение зависимостей на зависимости проекта и зависимости разработки

Я зависимости на 3 части разделяю.

- проект
- CI (pytest, линтеры, ...)
- dev, то что нужно на локальной машине, обычно там только pre-commit.

На poetry посматриваю.

начиная с версии 1.2
Sign up to leave a comment.