Дата и время публикации:
Назначение и использование
1. Назначение
1.1 Что такое формат egg в Python
Логическая структура, которая отвечает реализацию определенной версии проекта Python, включающей в себя собственно код, ресурсы и метаданные. Существует несколько форматов, которые могут быть использованы для фактического представления Python и могут быть развиты самостоятельно.
Несмотря на большую полигамию, существуют два основных формата, реализующие накатывания отдельных дистрибутивов на базе проекта Python, которые с иронией стали называть яйца Python (Python egg), из которых получается знатная яичница в виде собранного и готового к дистрибьюции пакета Python:
- формат .egg является директорией или файлом архива zip, содержащие код Pуthon, ресурсы и вместе с ними в отдельной поддиректории EGG-INFO метаданные;
- формат .egg-info является также файлом или директорией, содержащий метаданные добавляемый к коду и ресурсам проекта Python [3.1].
При этом, так как собираюсь рассказывать о buildout, реализуемый Python-модулем zc.buildout, углубляться в тонкости использования форматов Python egg не буду, потому что эти форматы выбраны в нем основными [3.2].
1.2 Python-модуль zc.buildout
Реализует автоматическую сборку и тестирование собираемого программного обеспечения на всех этапах от разработки до момента выпуска версии программного продукта. При этом buidout основывается на принципах автоматизации процесса и неизменности воспроизведения [3.3]. Последняя подразумевает неизменность результата на повторных циклах сборки и тестирования для одной и той же конфигурации buidout в том же самом окружении.
2. Использование
2.1 Настройка и установка buildout
Как всегда, произвел зеркалирование репозитария Git в своем локальном хранилище [3.5] проекта свободно-распространяемого исходного кода zc.buildout [3.4], как показано в дампе 2.1.1
Дамп 2.1.1
$ git clone https://github.com/buildout/buildout.git python-buildout Клонирование в «python-buildout.git»… remote: Enumerating objects: 13610, done. remote: Counting objects: 100% (438/438), done. remote: Compressing objects: 100% (241/241), done. remote: Total 13610 (delta 217), reused 310 (delta 141), pack-reused 13172 Получение объектов: 100% (13610/13610), 4.28 MiB | 7.56 MiB/s, готово. Определение изменений: 100% (6697/6697), готово. ... $ sudo -u git git init --bare /home/git/repos/python-buildout.git ... git remote set-url origin git://localhost/python-buildout.git ... $ git push --mirror Перечисление объектов: 13610, готово. Подсчет объектов: 100% (13610/13610), готово. При сжатии изменений используется до 8 потоков Сжатие объектов: 100% (5500/5500), готово. Запись объектов: 100% (13610/13610), 4.28 MiB | 230.47 MiB/s, готово. Total 13610 (delta 6697), reused 13610 (delta 6697), pack-reused 0 remote: Resolving deltas: 100% (6697/6697), done. To git://localhost/python-buildout.git * [new branch] master -> master ...
Затем, выполнил и разместил пакет в индексном репозитарии Python — все операции показаны в дампе 2.1.2
Дамп 2.1.2
$ python3 -m build … Successfully built zc.buildout-3.0.0rc3.dev0.tar.gz and zc.buildout-3.0.0rc3.dev0-py2.py3-none-any.whl $ sudo -u git mkdir /home/git/pypisrv/zc.buildout … $ sudo install -m 0644 -o git -g git dist/zc.buildout-*-none-any.whl /home/git/pypisrv/zc.buildout $ sudo install -m 0644 -o git -g git dist/zc.buildout-*.tar.gz /home/git/pypisrv/zc.buildout … $ pip install --upgrade -U zc.buildout --extra-index-url http://localhost:8080/simple … Installing collected packages: setuptools, zc.buildout Attempting uninstall: setuptools Found existing installation: setuptools 60.10.0.post20220318 Uninstalling setuptools-60.10.0.post20220318: Successfully uninstalled setuptools-60.10.0.post20220318 Successfully installed setuptools-51.3.3 zc.buildout-2.13.6
При этом, рекомендую воспользоваться опцией --upgrade, которая позволяет устанавливать (обновлять) ранее установленные версии buildout. Так же возможно, в моем случае это было так, производит автоматическое разрешение версий зависимостей (других пакетов) к требуемым, как показано в дампе 2.1.2
2.2 Настройка и установка виртуального окружения CPython
Далее, рекомендуется настроить виртуальное окружение с использованием virtualenv [3.6]. Для чего, проводим такую же процедуру сохранения и публикацию проекта модуля virtualenv в хранилищах, как показано в дампе 2.2.1
Дамп 2.2.1
$ git clone https://github.com/pypa/virtualenv.git python-virtualenv … $ sudo -u git git init --bare /home/git/repos/python-virtualenv.git … $ git remote set-url origin git://localhost/python-virtualenv.git $ git push --mirror … $ python3 -m build … Successfully built virtualenv-20.13.4.dev4+g63c94af.tar.gz and virtualenv-20.13.4.dev4+g63c94af-py2.py3-none-any.whl … $ sudo install -m 0755 -o git -g git -d /home/git/pypisrv/virtualenv $ sudo install -m 0644 -o git -g git dist/virtualenv-*-none-any.whl /home/git/pypisrv/virtualenv $ sudo install -m 0644 -o git -g git dist/virtualenv-*.tar.gz /home/git/pypisrv/virtualenv $ pip install --upgrade -U virtualenv --extra-index-url http://localhost:8080/simple … Requirement already satisfied: six<2,>=1.9.0 in /usr/lib/python3/dist-packages (from virtualenv) (1.16.0) Installing collected packages: distlib, platformdirs, filelock, virtualenv Successfully installed distlib-0.3.4 filelock-3.6.0 platformdirs-2.5.1 virtualenv-20.13.4
После чего, можно приступить к настройки виртуального окружения, потому что начиная с версии 2.0 установленный zc.buildout больше не поддерживает изоляцию окружения сборки [3.7]. Поэтому один раз создаем виртуальное окружение, как показано в дампе 2.2.2
Дамп 2.2.2
$ mkdir -p ~/Projects/python-venv/ && cd ~/Projects/python-venv/ $ pip freeze > requirements.txt $ pip freeze -q -r requirements.txt | sed '/freeze/,$ d' > requirements-froze.txt $ mv requirements-froze.txt requirements.txt
При этом будте готовы поломать голову и не терять время, чтобы устранить битые зависимости из requirements.txt, например — отсутствующий Brlapi, если задумаете использовать pip freeze для этого. Поэтому рекомендую следующий рецепт, чтобы создать локальное окружение CPython, изолированное от глобального, как показано в дампе 2.2.3
Дамп 2.2.3
$ virtualenv -p python3 venv created virtual environment CPython3.9.2.final.0-64 in 485ms creator CPython3Posix(dest=/home/user/Projects/python-venv/venv, clear=False, no_vcs_ignore=False, global=False) seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/user/.local/share/virtualenv) added seed packages: pip==22.0.4, setuptools==60.10.0, wheel==0.37.1 activators BashActivator,CshellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator ... $ . venv/bin/activate (venv) $ pip install --upgrade -U zc-buildout --extra-index-url http://localhost:8080/simple
При этом нужно помнить, что часто приводимая в некоторых источниках опция --no-site-packages в версии virtualenv-20 и выше была удалена и больше не используется [3.11]. Так же, как вариант, только что созданное окружение может быть создано и использовано, как показано в дампе 2.2.4
Дамп 2.2.4
$ virtualenv -p python3 venv-shellenv $ cd venv-shellenv $ bin/pip install --upgrade -U zc-buildout --extra-index-url http://localhost:8080/simple $ mkdir src && cd src && git clone http://localhost/python-shellenv.git -b v1.4
Недостатком использования локального виртуального окружения СPython является в постоянном контроле за тем , что какими инструментальными средствами из глобального или только что созданного виртуального окружения. Даже несмотря на то, что была выполнена команда `source bin/activate`, а командная строка начинается с имени корневой директории, где на ходится это окружение, как показано в дампе 2.2.5
Дамп 2.2.5
user@myhost:~/Projects/python-venv/venv-shellenv$ source bin/activate (venv-shellenv) user@home2:~/Projects/python-venv/venv-shellenv$
2.3 Методанные запуска и инициализации Buildout
Реализуются с помощью команды `buildout bootstrap` и требует наличие файла buildout.cfg, который можно сгнерировать с помощью команды buildout init и как показано в дампе 2.3.1
Дамп 2.3.1
(venv-shellenv) ~/.../src/python-shellenv/$ ../../bin/buildout init Creating '/home/user/Projects/python-venv/venv-shellenv/src/python-shellenv/buildout.cfg'. Creating directory '~/.../src/python-shellenv/eggs'. Creating directory '~/.../src/python-shellenv/bin'. Creating directory '~/.../src/python-shellenv/parts'. Creating directory '~/.../src/python-shellenv/develop-eggs'. Generated script '~/.../src/python-shellenv/bin/buildout'.
В результате в корне будут сформированы дополнительные файлы и директории/, которые показаны в дампе 2.3.2 в качестве неотслеживаемых и добавленные мной в файл .gitignore
Дамп 2.3.2
(venv-shellenv) ~/.../src/python-shellenv/$ git status ... Неотслеживаемые файлы: (используйте «git add <файл>…», чтобы добавить в то, что будет включено в коммит) bin/ buildout.cfg develop-eggs/ parts/ eggs/
Кроме файла buildout.cfg , который имеет секцию [buildout] и пустой список частей, именуемый "parts" и содержащий отдельные часть, которые будем добавлять по ходу пьесы [3.13]. Файл получаемый после выполнения команды buildout init показан в дампе 2.3.3
Дамп 2.3.2
~/.../src/python-shellenv/$ cat $ cat buildout.cfg [buildout] parts = ...
Каждая часть в списке "parts" ассоциируется с рецептом (recipe), который делает свою часть работы по выкатыванию яйца (egg), например
- zc.recipe.egg является широко используемым накатывания в директории eggs и генерации скриптов внутри директории bin/
- zc.recipe.macro предоставляет набор рецептов или даже частей, чтобы создавать динамически целые макросекции или их отдельные параметры, что позволяет разделять данные и их формата вывода [3.14]; при этом zc.recipe.macro и zc.recipe.egg реализуют отдельные задачи и не стоит их путать;
- git-recipe клонирование репозитария Git и извлечение рабочей копии части проекта или той его части [3.15]: в моем случае обеспечивает обновление к текущей копии, которая прошла слияние в ветви master/main;
Так, в моем случае, использование zc.recipe.egg и git-recipe позволит удовлетворять зависимости, которые указаны в файле pyproject.toml опции "requires=" секции, где кроме отвечающих за сборку проекта модулей еще указана зависимость от модуля python-dotenv, поэтому, если нужно прописать загрузку и установку этого модуля в отдельных частях, как показано в дамп 2.3.3
Дамп 2.3.3
[buildout] parts = git-dotenv dotenv [git-dotenv] recipe = git-recipe repository = git://localhost/python-dotenv.git ref = origin/master download-directory = ${buildout:directory}/parts/ [dotenv] recipe = zc.recipe.egg eggs = python-dotenv ...
В результате, должно получится что-то подобное, как показано в дампе 2.3.4
Дамп 2.3.4
(venv-shellenv) ~/.../src/python-shellenv/$ ../../bin/buildout -c buildout.cfg Getting distribution for 'git-recipe'. Got git-recipe 0.2.7. Getting distribution for 'zc.recipe.egg>=2.0.6'. Got zc.recipe.egg 2.0.7. Uninstalling git-dotenv. Installing git-dotenv. Updating dotenv. Getting distribution for 'python-dotenv'. Got python-dotenv 0.19.2.
2.4 Директории используемые или автоматически создаваемые buildout
Директория bin/
Содержит различные выполняемые файлы, включая команду buildout и скрипты управления экземплярами, например, пакета 'python-dotenv';
Директория eggs/
Содержит файлы и директории в формате eggs, которые будут загружены buildout, что будет неявно активировано скриптом управления экземпляром в директории bin/;
Директория downloads/
Содержит код и данные, управляемые buildout. В моем случае, это закаченный из локального репозитария пакета 'python-dotenv'
Директория var/
Содержит дополнительно импортируемые экземпляры модулей, журналирование действий, например, по запуску и управления баз данных, сервисом и служб [3.17]
При этом,
${buildout:directory} — корневая (рабочая) директория, в корне которой запускается buildout и расширяемая до абсолютного пути, как показано в дампе 2.3.4
${bin-buildout:directory} — директория bin/ и расширяемая до полного пути относительно корневая (рабочая) директория buildout
Таким образом, после выполнения buildout модуль python-shellenv приобритет вид и вышеперечисленные директории, как показано в дампе 2.4.1
Дамп 2.4.1
$ exa --tree --ignore-glob="*~|__pycache__|dist|*.egg-info" -L1 --sort=type . ├── bin/ ├── develop-eggs/ ├── eggs/ ├── parts/ ├── src/ ├── LICENSE ├── README.md ├── buildout.cfg ├── pyproject.toml └── setup.cfg
2.5 Совместное использование с модулем setuptools
Для сборки пакета 'python-build' с использованием локального virtualenv и построение копии в формате python egg c помощью buildout, мне понадобилось добавить setup.py на ряду с buildout.cfg [3.18] в корень проекта. Поэтому мне пришлось добавить в проект python-shellenv файл setup.py, почему?
Потому что после того, как мной были добавлены опции 'develop=' и 'egg=' в секцию [buildout], как показано в листинге 2.5.1, запуск buildout в моем локальном окружении был завершен с ошибкой, что setup.py не был найден.
Листинг 2.5.1
[buildout] parts = git-dotenv dotenv python develop = . eggs = shellenv [git-dotenv] recipe = git-recipe repository = git://localhost/python-dotenv.git ref = origin/master # download-directory = ${buildout:directory}/parts/ [dotenv] recipe = zc.recipe.egg eggs = python-dotenv [python] recipe = zc.recipe.egg interpreter = python eggs = ${buildout:eggs}
Файл setup.py не был найден отображается ошибкой, как показано в дампе 2.5.2
Дамп 2.5.2
(venv-shellenv) ~/.../src/python-shellenv/$ ../../bin/buildout Develop: '${HOME}/.../venv-shellenv/src/python-shellenv/.' Traceback (most recent call last): File "/tmp/tmphg8bxny1", line 13, inwith open('${HOME}/.../venv-shellenv/src/python-shellenv/./setup.py') as f: FileNotFoundError: [Errno 2] No such file or directory: '${HOME}/.../venv-shellenv/src/python-shellenv/./setup.py' ...
Поэтому мной был написан дублирующий setup.cfg скрипт setup.py, фрагмент которого приведен в листинге 2.5.3
Листинг 2.5.3
from setuptools.config import read_configuration ... setup( name = "shellenv", version=get_package_version(), url = 'https://github.com/rjaan/python-shellenv.git', license = 'PSF', description = "print SHELL's enviroment variables on standard output", author = 'Andrey Rzhavskov', packages = find_packages(), package_dir = {'': 'src'}, install_requires = [ 'setuptools>=42', 'python-dotenv>=0.19' ], python_requires = '>=3.8', long_description=read('README.md'), classifiers=[ "Programming Language :: Python :: 3", "OSI Approved::Python Software Foundation License", "Operating System :: OS Independent" # Get strings from # http://pypi.python.org/pypi?%3Aaction=list_classifiers ], zip_safe=True, options={"bdist_wheel": {"universal": True}}, platforms=["any"], )
Результат выполнения buildout показан в дампе 2.5.4
Дамп 2.5.4
../../bin/buildout -c buildout.cfg Creating directory '/home/user/Projects/python-venv/venv-shellenv/src/python-shellenv/eggs'. Creating directory '/home/user/Projects/python-venv/venv-shellenv/src/python-shellenv/bin'. Creating directory '/home/user/Projects/python-venv/venv-shellenv/src/python-shellenv/parts'. Creating directory '/home/user/Projects/python-venv/venv-shellenv/src/python-shellenv/develop-eggs'. Develop: '/home/user/Projects/python-venv/venv-shellenv/src/python-shellenv/.' Getting distribution for 'git-recipe'. Got git-recipe 0.2.7. Getting distribution for 'zc.recipe.egg>=2.0.6'. Got zc.recipe.egg 2.0.7. Uninstalling python. Uninstalling dotenv. Uninstalling git-dotenv. Installing git-dotenv. Installing dotenv. Generated script '/home/user/Projects/python-venv/venv-shellenv/src/python-shellenv/bin/dotenv'. Installing python. Generated interpreter '/home/user/Projects/python-venv/venv-shellenv/src/python-shellenv/bin/python'.
3. Библиография
3.1 Buildout 1.2.1 documentation — Buildout Tutorial
3.2 Buildout's Getting started — egg
3.3 Buildout's Getting started
3.5 Git to deploy own git server
3.8 How to create python development environment virtualenv using setup
3.10 virtualenv n site packages pip 1842
3.11 virtualenv-virtualenvwrapper virtualenv error unrecognized arguments no sit
3.12 What is setup.py
3.13 Plane — Understanding buildout.cfg the-zope2-section
3.14 Python's package zc.recipe.macro
3.15 Python's package git-recipe
3.17 Plone — Creating a buildout for your project
3.18 whats a minimal buildout cfg file for a python package
3.19 Setuptools