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.
Для собранных дистрибутивов доступны следующие форматы:
Формат |
Описание |
Примечания |
---|---|---|
|
gzipped tar файл ( |
(1) |
|
bzipped tar файл ( |
|
|
xzipped tar-файл ( |
|
|
сжатый tar-файл ( |
(3) |
|
tar-файл ( |
|
|
zip-файл ( |
(2),(4) |
|
RPM |
(5) |
|
Solaris pkgtool |
|
|
HP-UX swinstall |
|
|
Microsoft Installer. |
Изменено в версии 3.5: Добавлена поддержка формата xztar
.
Примечания:
по умолчанию в Unix
по умолчанию в Windows
требует внешней утилиты compress.
требует либо внешней утилиты zip, либо модуля
zipfile
(часть стандартной библиотеки Python, начиная с Python 1.6)требует внешней утилиты 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 |
Опция сценария настройки Distutils |
---|---|
Имя |
|
Резюме (в преамбуле) |
|
Версия |
|
Поставщик |
|
Авторское право |
|
Url |
|
%description (раздел) |
|
Кроме того, в файлах .spec
есть много опций, которые не имеют соответствующих опций в сценарии установки. Большинство из них обрабатывается с помощью опций команды bdist_rpm следующим образом:
Опция или секция файла RPM |
bdist_rpm опция |
значение по умолчанию |
---|---|---|
Релиз |
|
«1» |
Группа |
|
«Развитие/Библиотеки» |
Поставщик |
|
(см. выше) |
Упаковщик |
|
(нет) |
Предоставляет |
|
(нет) |
Требуется |
|
(нет) |
Конфликты |
|
(нет) |
Обсолеты |
|
(нет) |
Распространение |
|
(нет) |
BuildRequires |
|
(нет) |
Икона |
|
(нет) |
Очевидно, что вводить даже несколько таких опций в командной строке будет утомительно и чревато ошибками, поэтому обычно лучше поместить их в конфигурационный файл setup, setup.cfg
—см. раздел Запись файла конфигурации установки. Если вы распространяете или упаковываете много дистрибутивов модулей Python, вы можете захотеть поместить опции, применимые ко всем из них, в ваш личный конфигурационный файл Distutils (~/.pydistutils.cfg
). Если вы хотите временно отключить этот файл, вы можете передать опцию --no-user-cfg
в setup.py
.
Сборка бинарного RPM-пакета состоит из трех этапов, все из которых автоматически обрабатываются Distutils:
создать файл
.spec
, который описывает пакет (аналогично скрипту установки Distutils; на самом деле, большая часть информации в скрипте установки оказывается в файле.spec
)создать исходный RPM
создать «бинарный» 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
.