5. Создание построенных распределений

Примечание

Этот документ сохраняется исключительно до тех пор, пока документация setuptools на сайте https://setuptools.readthedocs.io/en/latest/setuptools.html не будет независимо охватывать всю соответствующую информацию, включенную сюда в настоящее время.

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

Собранный дистрибутив - это способ максимально упростить жизнь установщикам дистрибутива вашего модуля: для пользователей Linux-систем на базе RPM это бинарный RPM; для пользователей Windows это исполняемый инсталлятор; для пользователей Linux на базе Debian это пакет Debian; и так далее. Очевидно, что ни один человек не сможет создать собранные дистрибутивы для всех платформ под солнцем, поэтому Distutils предназначен для того, чтобы разработчики модулей могли сосредоточиться на своей специальности - написании кода и создании исходных дистрибутивов - в то время как промежуточный вид, называемый пакетчиками, возникает для превращения исходных дистрибутивов в собранные дистрибутивы для стольких платформ, сколько существует пакетчиков.

Конечно, разработчик модуля может быть своим собственным упаковщиком; или упаковщик может быть добровольцем «где-то там», у которого есть доступ к платформе, которой нет у оригинального разработчика; или это может быть программное обеспечение, периодически берущее новые исходные дистрибутивы и превращающее их в собранные дистрибутивы для стольких платформ, к которым у этого программного обеспечения есть доступ. Независимо от того, кто это, упаковщик использует сценарий установки и семейство команд bdist для создания собранных дистрибутивов.

В качестве простого примера, если я выполню следующую команду в дереве исходных текстов Distutils:

python setup.py bdist

затем Distutils собирает дистрибутив моего модуля (в данном случае сам Distutils), выполняет «фальшивую» установку (также в каталоге build) и создает тип собранного дистрибутива по умолчанию для моей платформы. Формат по умолчанию для собранных дистрибутивов - это «тупой» tar-файл на Unix и простой исполняемый инсталлятор на Windows. (Этот tar-файл считается «тупым», потому что для работы он должен быть распакован в определенном месте).

Таким образом, приведенная выше команда в Unix-системе создает Distutils-1.0.plat.tar.gz; распаковка этого тарбала из нужного места устанавливает Distutils так же, как если бы вы скачали исходный дистрибутив и выполнили команду python setup.py install. («Правильное место» - это либо корень файловой системы, либо каталог Python prefix, в зависимости от опций, заданных в команде bdist_dumb; по умолчанию дистрибутивы dumb устанавливаются относительно каталога prefix).

Очевидно, что для чистых дистрибутивов Python это не проще, чем просто выполнить python setup.py install— но для нечистых дистрибутивов, которые включают расширения, которые должны быть скомпилированы, это может означать разницу между тем, сможет ли кто-то использовать ваши расширения или нет. Создание «умных» собранных дистрибутивов, таких как RPM-пакет или исполняемый установщик для Windows, гораздо удобнее для пользователей, даже если ваш дистрибутив не включает никаких расширений.

Команда bdist имеет опцию --formats, аналогичную команде sdist, которую можно использовать для выбора типов собираемого распределения для генерации: например,

python setup.py bdist --format=zip

при запуске на Unix-системе создаст Distutils-1.0.plat.zip—далее, этот архив будет распакован из корневого каталога для установки Distutils.

Для собранных дистрибутивов доступны следующие форматы:

Формат

Описание

Примечания

gztar

gzipped tar файл (.tar.gz)

(1)

bztar

bzipped tar файл (.tar.bz2)

xztar

xzipped tar-файл (.tar.xz)

ztar

сжатый tar-файл (.tar.Z)

(3)

tar

tar-файл (.tar)

zip

zip-файл (.zip)

(2),(4)

rpm

RPM

(5)

pkgtool

Solaris pkgtool

sdux

HP-UX swinstall

msi

Microsoft Installer.

Изменено в версии 3.5: Добавлена поддержка формата xztar.

Примечания:

  1. по умолчанию в Unix

  2. по умолчанию в Windows

  3. требует внешней утилиты compress.

  4. требует либо внешней утилиты zip, либо модуля zipfile (часть стандартной библиотеки Python, начиная с Python 1.6)

  5. требует внешней утилиты rpm, версии 3.0.4 или лучше (используйте rpm --version, чтобы узнать, какая у вас версия).

Не обязательно использовать команду bdist с опцией --formats; вы также можете использовать команду, которая непосредственно реализует интересующий вас формат. Некоторые из этих «подкоманд» bdist на самом деле генерируют несколько похожих форматов; например, команда bdist_dumb генерирует все «тупые» форматы архивов (tar, gztar, bztar, xztar, ztar и zip), а bdist_rpm генерирует бинарные и исходные RPM. Подкоманды bdist и форматы, генерируемые каждой из них, следующие:

Команда

Форматы

bdist_dumb

tar, gztar, bztar, xztar, ztar, zip

bdist_rpm

об/мин, srpm

bdist_msi

msi

Примечание

bdist_msi устарел с версии Python 3.9.

В следующих разделах подробно описаны отдельные команды bdist_*.

5.1. Создание пакетов RPM

Формат RPM используется во многих популярных дистрибутивах Linux, включая Red Hat, SuSE и Mandrake. Если один из них (или любой другой дистрибутив Linux на основе RPM) является вашей обычной средой, создание пакетов RPM для других пользователей этого дистрибутива является тривиальной задачей. В зависимости от сложности вашего модульного дистрибутива и различий между дистрибутивами Linux, вы также можете создавать RPM-пакеты, работающие в разных дистрибутивах на базе RPM.

Обычный способ создания RPM дистрибутива вашего модуля заключается в выполнении команды bdist_rpm:

python setup.py bdist_rpm

или команда bdist с опцией --format:

python setup.py bdist --formats=rpm

Первая позволяет указать опции, специфичные для RPM; вторая позволяет легко указать несколько форматов за один запуск. Если вам нужно сделать и то, и другое, вы можете явно указать несколько команд bdist_* и их опции:

python setup.py bdist_rpm --packager="John Doe <jdoe@example.org>"

Создание пакетов RPM управляется файлом .spec, так же как использование Distutils управляется сценарием установки. Чтобы облегчить вам жизнь, команда bdist_rpm обычно создает файл .spec на основе информации, которую вы предоставляете в сценарии установки, в командной строке и в любых конфигурационных файлах Distutils. Различные опции и секции в файле .spec вытекают из опций в сценарии установки следующим образом:

Опция или секция файла RPM .spec

Опция сценария настройки Distutils

Имя

name

Резюме (в преамбуле)

description

Версия

version

Поставщик

author и author_email, или — & maintainer и maintainer_email

Авторское право

license

Url

url

%description (раздел)

long_description

Кроме того, в файлах .spec есть много опций, которые не имеют соответствующих опций в сценарии установки. Большинство из них обрабатывается с помощью опций команды bdist_rpm следующим образом:

Опция или секция файла RPM .spec

bdist_rpm опция

значение по умолчанию

Релиз

release

«1»

Группа

group

«Развитие/Библиотеки»

Поставщик

vendor

(см. выше)

Упаковщик

packager

(нет)

Предоставляет

provides

(нет)

Требуется

requires

(нет)

Конфликты

conflicts

(нет)

Обсолеты

obsoletes

(нет)

Распространение

distribution_name

(нет)

BuildRequires

build_requires

(нет)

Икона

icon

(нет)

Очевидно, что вводить даже несколько таких опций в командной строке будет утомительно и чревато ошибками, поэтому обычно лучше поместить их в конфигурационный файл setup, setup.cfg—см. раздел Запись файла конфигурации установки. Если вы распространяете или упаковываете много дистрибутивов модулей Python, вы можете захотеть поместить опции, применимые ко всем из них, в ваш личный конфигурационный файл Distutils (~/.pydistutils.cfg). Если вы хотите временно отключить этот файл, вы можете передать опцию --no-user-cfg в setup.py.

Сборка бинарного RPM-пакета состоит из трех этапов, все из которых автоматически обрабатываются Distutils:

  1. создать файл .spec, который описывает пакет (аналогично скрипту установки Distutils; на самом деле, большая часть информации в скрипте установки оказывается в файле .spec)

  2. создать исходный RPM

  3. создать «бинарный» RPM (который может содержать или не содержать бинарный код, в зависимости от того, содержит ли дистрибутив вашего модуля расширения Python)

Обычно RPM объединяет последние два шага вместе; когда вы используете Distutils, все три шага обычно объединяются вместе.

При желании вы можете разделить эти три шага. Вы можете использовать опцию --spec-only, чтобы заставить bdist_rpm просто создать файл .spec и выйти; в этом случае файл .spec будет записан в «каталог распространения» - обычно dist/, но настраивается с помощью опции --dist-dir. (Обычно файл .spec оказывается глубоко в «дереве сборки», во временном каталоге, созданном опцией bdist_rpm).

5.2. Перекрестная компиляция в Windows

Начиная с Python 2.6, distutils способен осуществлять кросс-компиляцию между платформами Windows. На практике это означает, что, установив соответствующие инструменты, вы можете использовать 32-разрядную версию Windows для создания 64-разрядных расширений и наоборот.

Для сборки под альтернативную платформу укажите опцию --plat-name в команде сборки. В настоящее время допустимыми значениями являются „win32“ и „win-amd64“. Например, на 32-разрядной версии Windows вы можете выполнить:

python setup.py build --plat-name=win-amd64

для создания 64-разрядной версии вашего расширения.

создаст 64-разрядный исполняемый файл установки на вашей 32-разрядной версии Windows.

Для кросс-компиляции вы должны загрузить исходный код Python и кросс-компилировать сам Python для платформы, на которую вы нацелены - это невозможно из бинарной установки Python (поскольку .lib и т.д. файлы для других платформ не включены). На практике это означает, что пользователю 32-битной операционной системы придется использовать Visual Studio 2008 для открытия решения PCbuild/PCbuild.sln в дереве исходного кода Python и сборки конфигурации «x64» проекта „pythoncore“, прежде чем станет возможной кросс-компиляция расширений.

Обратите внимание, что по умолчанию Visual Studio 2008 не устанавливает 64-битные компиляторы или инструменты. Вам может понадобиться повторно выполнить процесс установки Visual Studio и выбрать эти инструменты (использование Control Panel->[Add/Remove] Programs является удобным способом проверки или изменения существующей установки).

5.2.1. Постинсталляционный скрипт

Начиная с Python 2.3, сценарий после установки можно указать с помощью опции --install-script. Основное имя сценария должно быть указано, а имя файла сценария также должно быть указано в аргументе scripts функции setup.

Этот скрипт будет запущен во время установки на целевой системе после копирования всех файлов, при этом argv[1] будет иметь значение -install, и снова во время деинсталляции перед удалением файлов, при этом argv[1] будет иметь значение -remove.

Сценарий установки запускается встроенным в программу установки windows, каждый вывод (sys.stdout, sys.stderr) перенаправляется в буфер и будет отображаться в графическом интерфейсе после завершения работы сценария.

Некоторые функции, особенно полезные в этом контексте, доступны как дополнительные встроенные функции в сценарии установки.

directory_created(path)
file_created(path)

Эти функции должны вызываться, когда каталог или файл создается скриптом postinstall во время установки. Это зарегистрирует path в программе деинсталляции, чтобы он был удален при деинсталляции дистрибутива. Для безопасности каталоги удаляются только в том случае, если они пусты.

get_special_folder_path(csidl_string)

Эту функцию можно использовать для получения местоположения специальных папок в Windows, например, в меню «Пуск» или на рабочем столе. Она возвращает полный путь к папке. csidl_string должна быть одной из следующих строк:

"CSIDL_APPDATA"

"CSIDL_COMMON_STARTMENU"
"CSIDL_STARTMENU"

"CSIDL_COMMON_DESKTOPDIRECTORY"
"CSIDL_DESKTOPDIRECTORY"

"CSIDL_COMMON_STARTUP"
"CSIDL_STARTUP"

"CSIDL_COMMON_PROGRAMS"
"CSIDL_PROGRAMS"

"CSIDL_FONTS"

Если папка не может быть извлечена, выдается сообщение OSError.

Какие папки доступны, зависит от конкретной версии Windows, а также, возможно, от конфигурации. За подробностями обратитесь к документации Microsoft по функции SHGetSpecialFolderPath().

create_shortcut(target, description, filename[, arguments[, workdir[, iconpath[, iconindex]]]])

Эта функция создает ярлык. target - это путь к программе, которая будет запущена ярлыком. description - это описание ярлыка. filename - это название ярлыка, который будет видеть пользователь. arguments указывает аргументы командной строки, если таковые имеются. workdir - рабочий каталог программы. iconpath - файл, содержащий значок для ярлыка, а iconindex - индекс значка в файле iconpath. За подробностями обратитесь к документации Microsoft по интерфейсу IShellLink.

Вернуться на верх