Содержание страницы
5. Создание сборок (built distributions)¶Creating Built Distributions
«Готовый дистрибутив» – это то, что обычно понимают как «бинарный пакет» или «установщик» (в зависимости от контекста). При этом он не обязательно является бинарным, поскольку может содержать только исходный код Python и/или байт-код; его не называют пакетом, так как это слово уже занято в Python. (А «установщик» – термин, относящийся к миру обычных настольных систем.)
Готовый дистрибутив – это способ максимально упростить задачу установки вашего дистрибутива модуля: для пользователей RPM-систем Linux это бинарный RPM; для пользователей Windows – исполняемый установщик; для пользователей Debian-систем Linux – пакет Debian и так далее. Очевидно, что один человек не сможет создавать готовые дистрибутивы для всех платформ мира, поэтому Distutils спроектированы так, чтобы разработчики модулей могли сосредоточиться на своей специализации – написании кода и создании исходных дистрибутивов, – а тем временем появляется промежуточное звено, называемое упаковщиками (packagers), которые превращают исходные дистрибутивы в готовые для стольких платформ, сколько существует упаковщиков.
Разумеется, разработчик модуля может сам быть упаковщиком; или упаковщиком может быть волонтёр, имеющий доступ к платформе, которой нет у разработчика; или это может быть программа, которая периодически забирает новые дистрибутивы исходников и превращает их в сборки для как можно большего числа доступных платформ. Кем бы ни был упаковщик, он использует скрипт setup и семейство команд bdist для создания сборок.
В качестве простого примера: если выполнить следующую команду в дереве исходного кода Distutils:
python setup.py bdist
затем Distutils собирает мой дистрибутив модуля (в данном случае сам Distutils), выполняет «фиктивную» установку (также в каталог build) и создаёт собранный дистрибутив типа по умолчанию для моей платформы. Формат по умолчанию для собранных дистрибутивов – «простой» tar-файл в Unix и простой исполняемый установщик в Windows. (Этот tar-файл считается «простым», потому что для работы его нужно распаковать в определённое место.)
Таким образом, указанная выше команда в Unix-системе создаёт Distutils-1.0.plat.tar.gz; распаковка этого tarball'а из правильного места устанавливает Distutils так же, как если бы вы загрузили исходный дистрибутив и выполнили python setup.py install. («Правильное место» – это либо корень файловой системы, либо каталог prefix Python, в зависимости от параметров, переданных команде 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.
Доступные форматы для готовых дистрибутивов:
| Формат | Описание | Примечания |
|---|---|---|
| gztar | gzip-сжатый tar-файл (.tar.gz) | (1),(3) |
| ztar | сжатый tar-файл (.tar.Z) | (3) |
| tar | tar-файл (.tar) | (3) |
| zip | zip-файл (.zip) | (2),(4) |
| rpm | RPM | (5) |
| pkgtool | Solaris pkgtool | |
| sdux | HP-UX swinstall | |
| wininst | самораспаковывающийся ZIP-файл для Windows | (4) |
| msi | Установщик Microsoft. |
Примечания:
- по умолчанию на Unix
- по умолчанию на Windows
- требует внешних утилит: tar и, возможно, одной из gzip, bzip2 или compress
- требует либо внешнюю утилиту zip, либо модуль zipfile (входит в стандартную библиотеку Python, начиная с Python 1.6)
- требует внешней утилиты rpm версии 3.0.4 или выше (используйте rpm --version, чтобы узнать установленную версию)
Необязательно использовать команду bdist с опцией --formats; можно также напрямую использовать команду, реализующую нужный формат. Некоторые из этих «подкоманд» bdist на самом деле генерируют несколько похожих форматов; например, команда bdist_dumb создаёт все «простые» форматы архивов (tar, ztar, gztar и zip), а bdist_rpm создаёт как бинарные, так и исходные RPM. Подкоманды bdist и создаваемые ими форматы перечислены ниже:
| Команда | Форматы |
|---|---|
| bdist_dumb | tar, ztar, gztar, zip |
| bdist_rpm | rpm, srpm |
| bdist_wininst | wininst |
| bdist_msi | msi |
В следующих разделах приводятся подробности о каждой команде bdist_*.
5.1. Создание RPM-пакетов¶Creating RPM packages
Формат RPM используется во многих популярных дистрибутивах Linux, включая Red Hat, SuSE и Mandrake. Если один из них (или любой другой дистрибутив на основе 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>" \
bdist_wininst --target-version="2.0"
Создание RPM-пакетов управляется файлом .spec, примерно так же, как Distutils управляется скриптом установки. Чтобы упростить вам жизнь, команда bdist_rpm обычно создаёт файл .spec на основе информации, которую вы предоставляете в скрипте установки, в командной строке и в любых конфигурационных файлах Distutils. Различные опции и разделы в файле .spec берутся из опций скрипта установки следующим образом:
| Опция или раздел файла RPM .spec | Параметр сценария setup Distutils |
|---|---|
| Имя | имя |
| Summary (в преамбуле) | описание |
| Версия | версия |
| Поставщик | author и author_email, или – & maintainer и maintainer_email |
| Авторские права | лицензия |
| URL | url |
| %description (раздел) | long_description |
Кроме того, в файлах .spec есть много опций, которым нет соответствующих опций в скрипте установки. Большинство из них обрабатываются через опции команды bdist_rpm следующим образом:
| RPM .spec опция или раздел | Параметр команды bdist_rpm | значение по умолчанию |
|---|---|---|
| Версия | release | “1” |
| Группа | group | “Разработка/Библиотеки” |
| Поставщик | vendor | (см. выше) |
| Упаковщик | packager | (нет) |
| Предоставляет | provides | (нет) |
| Требует | требует | (нет) |
| Конфликтует | конфликтует | (нет) |
| Заменяет | заменяет | (нет) |
| Дистрибутив | distribution_name | (нет) |
| Зависимости сборки | build_requires | (нет) |
| Иконка | иконка | (нет) |
Очевидно, что передача даже нескольких таких параметров в командной строке была бы утомительной и чреватой ошибками, поэтому обычно лучше поместить их в конфигурационный файл установки, setup.cfg – см. раздел Написание конфигурационного файла установки. Если распространяется или пакуется множество дистрибутивов модулей Python, может оказаться удобным поместить параметры, применимые ко всем ним, в личный конфигурационный файл Distutils (~/.pydistutils.cfg).
Для сборки бинарного RPM-пакета необходимо выполнить три шага, все из которых aвтоматически обрабатываются Distutils:
- создаёт файл .spec, который описывает пакет (аналогично скрипту установки Distutils; на самом деле большая часть информации из скрипта установки попадает в файл .spec)
- создать исходный RPM
- создать «бинарный» RPM (который может содержать или не содержать двоичный код, в зависимости от того, содержит ли дистрибутив модуля расширения Python)
Обычно RPM объединяет последние два шага; при использовании Distutils все три шага обычно объединяются.
При желании вы можете разделить эти три шага. Используйте опцию --spec-only, чтобы команда bdist_rpm только создала файл .spec и завершилась; в этом случае файл .spec будет записан в «каталог распространения» – обычно dist/, но настраивается опцией --dist-dir. (Обычно файл .spec оказывается глубоко в «дереве сборки», во временном каталоге, созданном командой bdist_rpm.)
5.2. Создание установщиков Windows¶Creating Windows Installers
Исполняемые установщики – естественный формат для двоичных дистрибутивов на Windows. Они отображают удобный графический интерфейс, показывают информацию о распространяемом модуле, взятую из метаданных в сценарии установки, позволяют пользователю выбрать несколько параметров и запустить или отменить установку.
Поскольку метаданные берутся из сценария установки, создание установщиков для Windows обычно сводится к выполнению команды:
python setup.py bdist_wininst
или команда bdist с опцией --formats:
python setup.py bdist --formats=wininst
Если у вас дистрибутив из чистых модулей (содержит только чистые модули и пакеты Python), результирующий установщик будет не зависеть от версии и будет иметь имя вроде foo-1.0.win32.exe. Такие установщики можно создавать даже на платформах Unix или Mac OS X.
Если у вас дистрибутив не из чистых модулей, расширения можно создать только на платформе Windows, и они будут зависеть от версии Python. Имя файла установщика будет это отражать и теперь имеет форму foo-1.0.win32-py2.0.exe. Вам нужно создавать отдельный установщик для каждой версии Python, которую вы хотите поддерживать.
Установщик попытается скомпилировать чистые модули в байт-код после установки в целевой системе в обычном и оптимизирующем режиме. Если вы по какой-то причине не хотите, чтобы это происходило, вы можете запустить команду bdist_wininst с опцией --no-target-compile и/или опцией --no-target-optimize.
По умолчанию при запуске установщик показывает логотип «Python Powered», но можно указать собственный растровый файл Windows .bmp размером 152×261 с помощью параметра --bitmap.
При запуске установщик также отображает крупный заголовок в окне фона рабочего стола, который формируется из названия дистрибутива и номера версии. Его можно заменить другим текстом с помощью параметра --title.
Файл установщика записывается в «каталог дистрибутива» – обычно это dist/, но его можно изменить с помощью параметра --dist-dir.
5.3. Кросс-компиляция в Windows¶Cross-compiling on Windows
Начиная с Python 2.6, distutils поддерживает кросс-компиляцию между платформами Windows. На практике это означает, что при наличии установленных правильных инструментов можно использовать 32-битную версию Windows для создания 64-битных расширений и наоборот.
Чтобы выполнить сборку для другой платформы, укажите параметр --plat-name команды build. Допустимые значения: «win32», «win-amd64» и «win-ia64». Например, в 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. Постустановочный скрипт¶The Postinstallation script
Начиная с Python 2.3, можно указать сценарий послеустановки с помощью параметра --install-script. Необходимо указать базовое имя сценария, а имя файла сценария также должно быть перечислено в аргументе scripts функции setup.
Этот сценарий будет запущен на целевой системе во время установки после копирования всех файлов, при этом argv[1] устанавливается в -install, и повторно во время удаления перед удалением файлов, при этом argv[1] устанавливается в -remove.
Сценарий установки выполняется в составе установщика Windows, весь вывод (sys.stdout, sys.stderr) перенаправляется в буфер и отображается в графическом интерфейсе после завершения сценария.
Некоторые функции, особенно полезные в этом контексте, доступны как дополнительные встроенные функции в сценарии установки.
- directory_created(path)¶
- file_created(path)¶
Эти функции следует вызывать, когда каталог или файл создается сценарием после установки во время установки. Они регистрируют 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. Контроль учётных записей (UAC) в Windows Vista¶Vista User Access Control (UAC)
Начиная с Python 2.6, bdist_wininst поддерживает параметр --user-access-control. Значение по умолчанию – «none» (обработка UAC не выполняется), другие допустимые значения: «auto» (запрос на повышение UAC, если Python был установлен для всех пользователей) и «force» (всегда запрашивать повышение).