Создание собственных дистрибутивов
Примечание
Этот документ сохраняется только до тех пор, пока документация setuptools по адресу https://setuptools.readthedocs.io/en/latest/setuptools.html самостоятельно не охватывает всю актуальную информацию, сейчас представленную здесь.
«Собственный дистрибутив» — это то, что вы, вероятно, привыкли называть либо «бинарным пакетом», либо «инсталлятором» (в зависимости от вашего опыта). Однако он не обязательно является бинарным, так как может содержать только исходный код Python и/или байткод; и мы не называем его пакетом, потому что это слово уже используется в Python. (А «инсталлятор» — термин, специфичный для мира основных настольных систем.)
Собственный дистрибутив — это способ максимально упростить установку вашего модульного дистрибутива для пользователей: для пользователей систем Linux на основе RPM это бинарный RPM; для пользователей Windows — это установочный файл; для пользователей Linux на основе Debian — это пакет Debian и так далее. Очевидно, что ни один человек не сможет создать собственные дистрибутивы для каждой платформы, поэтому Distutils разработаны для того, чтобы позволить разработчикам модулей сосредоточиться на своей специализации — написании кода и создании исходных дистрибутивов — в то время как промежуточный вид под названием упаковщики возникает для преобразования исходных дистрибутивов в собственные дистрибутивы для как можно большего числа платформ, к которым у них есть доступ.
Конечно, разработчик модуля может быть и своим собственным упаковщиком; или упаковщик может быть добровольцем «где-то там», у которого есть доступ к платформе, которой нет у первоначального разработчика; или это может быть программное обеспечение, периодически загружающее новые исходные дистрибутивы и преобразующее их в собственные дистрибутивы для как можно большего числа платформ, к которым у него есть доступ. Независимо от того, кто они, упаковщик использует скрипт setup и семейство команд bdist для создания собственных дистрибутивов.
В качестве простого примера, если я выполню следующую команду в дереве исходных кодов Distutils:
python setup.py bdist
то Distutils создаст мой модульный дистрибутив (в данном случае — Distutils), выполнит «модельную» установку (также в каталоге build) и создаст дистрибутив по умолчанию для моей платформы. Формат дистрибутива по умолчанию — это «простой» архив tar на Unix и простой установочный файл на Windows. (Этот архив tar считается «простым», потому что для его работы его необходимо распаковать в определенном месте.)
Таким образом, данная команда в системе Unix создаст Distutils-1.0.plat.tar.gz; распаковка этого архива tar из правильного места установит Distutils так, как будто вы загрузили исходный дистрибутив и выполнили python setup.py install. («Правильное место» — это либо корень файловой системы, либо каталог Python prefix, в зависимости от параметров, переданных команде bdist_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.
Доступные форматы для собственных дистрибутивов:
Формат | Описание | Примечания |
|---|---|---|
| Архив tar, сжатый gzip ( | (1) |
| Архив tar, сжатый bzip2 ( | |
| Архив tar, сжатый xz ( | |
| Архив tar, сжатый ( | (3) |
| Архив tar ( | |
| Архив zip ( | (2),(4) |
| RPM | (5) |
| Solaris pkgtool | |
| HP-UX swinstall | |
| самораспаковывающийся архив ZIP для Windows | (4) |
| Установщик Microsoft. |
Изменено в версии 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 | rpm, srpm |
bdist_wininst | wininst |
bdist_msi | msi |
Примечание
bdist_wininst устарела с Python 3.8.
Примечание
bdist_msi устарела с Python 3.9.
В следующих разделах приводятся подробные сведения об отдельных командах bdist_*.
5.1. Создание пакетов RPM
Формат RPM используется многими популярными дистрибутивами Linux, включая Red Hat, SuSE и Mandrake. Если одна из этих (или любая другая основанная на RPM Linux-дистрибутив) является вашей обычной средой, создание пакетов 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>" \
bdist_wininst --target-version="2.0"
Создание пакетов RPM управляется файлом .spec, так же, как использование Distutils управляется скриптом setup. Для удобства команда bdist_rpm обычно создает файл .spec, основанный на информации, предоставленной вами в скрипте setup, в командной строке и в любых конфигурационных файлах Distutils. Различные опции и разделы в файле .spec выводятся из опций в скрипте setup следующим образом:
Опция или раздел файла RPM | Опция скрипта setup Distutils |
|---|---|
Имя |
|
Резюме (в преамбуле) |
|
Версия |
|
Поставщик |
|
Авторские права |
|
Url |
|
%description (раздел) |
|
Кроме того, есть много опций в файлах .spec, которые не имеют соответствующих опций в скрипте setup. Большинство из них обрабатываются через опции команды bdist_rpm следующим образом:
Опция или раздел файла RPM | Опция bdist_rpm | Значение по умолчанию |
|---|---|---|
Релиз |
| “1” |
Группа |
| “Разработка/Библиотеки” |
Поставщик |
| (см. выше) |
Упаковщик |
| (нет) |
Предоставляет |
| (нет) |
Требует |
| (нет) |
Конфликтует |
| (нет) |
Устаревает |
| (нет) |
Дистрибутив |
| (нет) |
Требуется для сборки |
| (нет) |
Иконка |
| (нет) |
Очевидно, предоставление даже нескольких из этих опций в командной строке было бы утомительным и подверженным ошибкам, поэтому лучше всего поместить их в конфигурационный файл setup, setup.cfg—см. раздел Написание конфигурационного файла Setup. Если вы распространяете или упаковываете много дистрибутивов модулей Python, вы можете поместить опции, которые применяются ко всем из них, в свой личный конфигурационный файл Distutils (~/.pydistutils.cfg). Если вы хотите временно отключить этот файл, вы можете передать опцию --no-user-cfg команде setup.py.
Существует три этапа создания двоичного пакета RPM, все из которых автоматически обрабатываются Distutils:
- создание файла
.spec, который описывает пакет (аналогично скрипту setup Distutils; фактически, большая часть информации из скрипта setup оказывается в файле.spec) - создание исходного RPM
- создание «двоичного» RPM (который может или не может содержать двоичный код, в зависимости от того, содержит ли ваш модульный дистрибутив расширения Python)
Обычно RPM объединяет последние два шага; при использовании Distutils все три шага обычно объединяются.
Если хотите, вы можете разделить эти три шага. Вы можете использовать опцию --spec-only для создания командой bdist_rpm только файла .spec и выхода; в этом случае файл .spec будет записан в «каталог дистрибуции» — обычно dist/, но настраиваемый с помощью опции --dist-dir. (Обычно файл .spec оказывается глубоко в «дереве сборки» в временной директории, созданной командой bdist_rpm.)
5.2. Создание установщиков для Windows
Предупреждение
bdist_wininst устарел с Python 3.8.
Предупреждение
bdist_msi устарел с Python 3.9.
Исполняемые установщики являются естественным форматом для двоичных дистрибутивов в Windows. Они отображают удобный графический пользовательский интерфейс, отображают некоторую информацию о модульном дистрибутиве, который будет установлен, взятую из метаданных в скрипте setup, позволяют пользователю выбрать несколько параметров и начать или отменить установку.
Поскольку метаданные берутся из скрипта setup, создание установщиков для Windows обычно так же просто, как запуск:
python setup.py bdist_wininst
или команда bdist с опцией --formats:
python setup.py bdist --formats=wininst
Если у вас чистый модульный дистрибутив (только чистые модули и пакеты Python), полученный установщик будет независимым от версии и иметь имя, подобное foo-1.0.win32.exe. Обратите внимание, что создание двоичных дистрибутивов wininst поддерживается только в системах Windows.
Если у вас есть дистрибутив, не являющийся чистым, расширения можно создать только в среде Windows, и они будут зависеть от версии Python. Имя файла установщика будет отражать это, и теперь имеет вид foo-1.0.win32-py2.0.exe. Вам нужно создать отдельный установщик для каждой поддерживаемой версии Python.
Установкащик попытается скомпилировать чистые модули в байткод после установки на целевую систему в обычном и оптимизирующем режиме. Если вы по какой-либо причине не хотите, чтобы это происходило, вы можете запустить команду bdist_wininst с опцией --no-target-compile и/или опцией --no-target-optimize.
По умолчанию установщик будет отображать логотип «Python Powered», но вы также можете предоставить собственный 152x261 битовый рисунок, который должен быть файлом Windows .bmp с опцией --bitmap.
Установкащик также отобразит большой заголовок на экране рабочего стола при запуске, построенный из имени вашего дистрибутива и номера версии. Это можно изменить на другой текст, используя опцию --title.
Файл установщика будет записан в «каталог дистрибуции» — обычно dist/, но настраиваемый с помощью опции --dist-dir.
5.3. Компиляция для разных платформ в 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-битную версию вашего расширения. Установщики Windows также поддерживают эту опцию, поэтому команда:
python setup.py build --plat-name=win-amd64 bdist_wininst
создаст исполняемый файл установки 64-битной версии на вашей 32-битной версии Windows.
Для кросс-компиляции необходимо загрузить исходный код Python и скомпилировать сам Python для целевой платформы — это невозможно из бинарной установки Python (так как файлы .lib и т. п. для других платформ не включены). На практике это означает, что пользователю с 32-битной операционной системой потребуется использовать Visual Studio 2008 для открытия PCbuild/PCbuild.sln решения в дереве исходного кода Python и сборки конфигурации «x64» проекта ‘pythoncore’, прежде чем станет возможной кросс-компиляция расширений.
Обратите внимание, что по умолчанию Visual Studio 2008 не устанавливает 64-битные компиляторы или инструменты. Возможно, потребуется повторно запустить процесс установки Visual Studio и выбрать эти инструменты (использование Панель управления->[Добавить/Удалить] программы является удобным способом проверки или изменения существующей установки).
5.3.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.
5.4. Контроль доступа пользователя в Vista (UAC)
Начиная с Python 2.6, bdist_wininst поддерживает опцию --user-access-control. По умолчанию она равна ‘none’ (т. е. обработка UAC не выполняется), а другие допустимые значения — ‘auto’ (что означает запрос на повышение привилегий UAC, если Python был установлен для всех пользователей) и ‘force’ (что означает всегда запрос на повышение привилегий).
Примечание
bdist_wininst устарел начиная с Python 3.8.
Примечание
bdist_msi устарел начиная с Python 3.9.
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.9/distutils/builtdist.html