Пакетирование и деплоймент
Сборка (повторение)
Главная ссылка Что умеет pip install:
- Скачать исходники, собрать и установить их
- Нужны сборочные зависимости
В случае модулей на Си это может быть очень непросто
- ⇒ часто встречаются прихаканные в исходниках бинарники (например, скомпилированные переводы)
- Скачать готовый пакет
Публиковать нужно и то, и то (лицензия, вопросы доработки и т. п.)
Пример: python -m build и что он создаёт
- sdist
- wheel
Что должно входить в wheel / sdist?
Для того, чтобы вместе с модулем упаковать какие-то дополнительные файлы, например, скомпилированные переводы, необходимо:
- Чтобы после сборки эти файлы (неважно, генераты или нет) оказались в каталоге с модулем
В секции options.package_data файла setup.cfg описать, какие файлы какому пакету принадлежат
Для того, чтобы упаковать в исходный дистрибутив дополнительные файлы (переводы, тесты и т. п.), их надо перечислить в заготовке файла-манифеста MANIFEST.in. Некоторые файлы включаются автоматически.
- Имеет смысл проследить за тем, чтобы в исходном дистрибутиве было всё, что лежит в репозитории
Пакетные зависимости
- Эксплуатационные зависимости
- Набор модулей, необходимых для эксплуатации приложения
- Обязательные и предполагаемые
- Включённые в python-инфраструктуру и все остальные
- Сборочные зависимости
Набор модулей и ПО, необходимый для разработки
+ Средства сборки
+ Средства тестирования
- Возможно, часть эксплуатационных зависимостей замещена квазиобъектами
Отслеживание зависимостей
∃ Более сложный инструмент — poetry, но он предписывает определённый workflow и скрывает многие действия под капотом, попробуем разобраться на нижнем уровне.
- Скопировать в чистое окружение и тупо запускать и добавлять в зависимости всё, из-за отсутствия чего падает)
Сделать pip freeze и угадать, что из этого всего понадобится при запуске
Соблюдать дисциплину с помощью pipenv:
Для установки чего не попадя — pip install что ни попадя
Для установки эксплуатационных зависимостей — pipenv install эксплуатационные зависимости
записывается в секцию [packages] файла Pipfile
pipenv install пакет обновляет Pipfile, даже если до этого был сделан pip install пакет
Для установки сборочных зависимостей — pipenv install -d сборочные зависимости)
Обновляет секцию [dev-packages] в Pipfile
При формировании дистрибутива / архива исходников
Эксплуатационные зависимости
Хранятся в setup.cfg или pyproject.toml
- можно отследить по наличию import-ов в модуле.
- В т. ч. автоматически, но
Есть прорва инструментов, ни одного годного
Часть из них импортит внутренности pip, что запрещено ☹ (пример: pip-check-reqs, оно пока работает)
Самый адекватный — поисковик python3 зависимостей в сборочнице ALT Linux Team
Запуск find project -name \*.py | python3 /usr/lib/rpm/python3.req.py
Сборочные зависимости
Хранятся в pyproject.toml, потому что определяют инструменты сборки
Можно отследить путём трассировки import-ов.
Но инструмента такого, похоже, нет!
Прототип инструмента, отслеживающего сборочные заивсимости
Пример такого инструмента: pip запускается из командной строки. Выдаёт довольно адекватную информацию, как минимум про репозиторий с примером
Составить словарь: какому из установленных пакетов какой файл принадлежит ( эта задача почему-то ещё не решена)
Учитывать только пакеты, установленные непосредственно, а не по зависимостям (например, с помощью pip list --not-required)
Запустить все инструменты сборки и тестирования с трассировкой (PYTHONVERBOSE=import python … или python -v …)
- Проанализировать журнал трассировки на предмет использования файлов, принадлежащих пакетам из локального окружения
Возможны ситуации, когда для сборки требуется инструмент, который был поставлен автоматом по зависимости, а то, что его требовало, для сборки не нужно.
Строгие VS нестрогие зависимости на версии
- Для публикации: скорее всего, нестрогие
- Для разработки (особенно совместной) — лучше строгие
Pipfile vs requirements.txt
Сам pip умеет в requirements.txt: pip install -r
Сборочные зависимости можно положить просто в отдельный файл (requirements-dev.txt, например)
pip freeze не умеет отличать «мусор» (левые пакеты) и пакеты установленные только по зависимостям от собственно зависимостей
- сборочные зависимсоти от эксплуатационных он тоже не отличает
- Приходится всё это отслеживать вручную
Pipfile нестандартен
нормально с ним работает только pipenv
- отличает все четыре вида установленных пакетов (см. выше)
- не умеет напрямую работать с «мусором»
только pipenv lock; pipenv --rm; pipenv sync (пересоздание окружения)
pipenv умеет отчитываться в формате requirements:
pipenv lock -r и
pipenv lock -r --dev-only
Точки входа
Для запуска python -m модуль в нём должен присутствовать __main__.py
Для создания стартового сценария в setup.cfg необходимо описать точки входа
Делоймент
Может быть разный, но мы остановимся на простой установке wheel:
pip install дистрибутив.wheel
- Не забывайте увеличивать номер версии (а то не обновится ☺)
- Не забывайте прописывать все нужные зависимости
- Не забывайте подкладывать все нужные файлы в wheel
Где искать файлы?
не в текущем каталоге!
не по полному пути!
Можно воспользоваться __file__:
resource = os.path.join(os.path.dirname(__file__), 'subdirectory', 'resource.file')
Это не работает, например, при запуске из .pyz
Рекомендуется освоить и использовать importlib.resources (и вообще importlib)
Обратите внимание на переводы — с ними та же история!
Пример
TODO более простой пример с дистрибутивными генератами, которые надо упаковать в wheel
- В частности, как работать с переводом, и откуда его потом брать
Д/З
Обеспечить в семестровом проекте:
- Сборку wheel
- Установку проекта в чистом окружении из этого wheel (должны притягиваться нужные зависимости)
- Сборку архива с исходниками
В архиве должны присутствовать все нужные файлы и некоторые полезные генераты (например, requirements-dev.txt)
- Запуск и полноценную работу проекта после установки в чистое окружение:
- проверить наличие зависимостей
- Проверить наличие непрогарммных файлов
- Проверить работу переводов
Это весь семестровый проект, готовый к сдаче!