Документация Python неофициальный перевод
Содержание страницы

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; распаковка этого tar-архива в правильном месте устанавливает 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 файл tar, сжатый gzip (.tar.gz) (1)
bztar файл tar, сжатый bzip2 (.tar.bz2)  
xztar xz-сжатый 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  
wininst самораспаковывающийся ZIP-файл для Windows (4)
msi Установщик Microsoft.  

Изменено в версии 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 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 управляется сценарием setup. Для упрощения работы команда bdist_rpm обычно создаёт файл .spec на основе информации, предоставленной в сценарии setup, в командной строке и в любых файлах конфигурации Distutils. Различные параметры и разделы в файле .spec берутся из параметров сценария setup следующим образом:

Параметр или раздел файла .spec Параметр сценария setup Distutils
Имя name
Summary (в преамбуле) description
Версия version
Поставщик author и author_email, или – & maintainer и maintainer_email
Авторские права license
URL url
%description (раздел) long_description

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

Параметр или раздел файла .spec Параметр команды bdist_rpm значение по умолчанию
Версия release “1”
Группа group “Разработка/Библиотеки”
Поставщик vendor (см. выше)
Упаковщик packager (нет)
Предоставляет provides (нет)
Требует requires (нет)
Конфликтует conflicts (нет)
Заменяет obsoletes (нет)
Дистрибутив distribution_name (нет)
Зависимости сборки build_requires (нет)
Иконка icon (нет)

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

Для сборки бинарного RPM-пакета необходимо выполнить три шага, все из которых aвтоматически обрабатываются 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. Создание установщиков WindowsCreating 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», но вы также можете предоставить собственное растровое изображение 152x261, которое должно быть файлом Windows .bmp с параметром --bitmap.

Установщик также будет отображать большой заголовок на окне фона рабочего стола при запуске, который формируется из имени вашего дистрибутива и номера версии. Это можно изменить на другой текст с помощью параметра --title.

Файл установщика будет записан в «каталог дистрибутива» – обычно dist/, но его можно настроить с помощью параметра --dist-dir.

5.3. Кросс-компиляция в WindowsCross-compiling on Windows

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

Чтобы собрать для другой платформы, укажите параметр --plat-name команды сборки. Допустимые значения на данный момент: '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 VistaVista User Access Control (UAC)

Начиная с Python 2.6, bdist_wininst поддерживает --user-access-control опцию. Значение по умолчанию – 'none' (означает, что обработка UAC не выполняется), а другие допустимые значения – 'auto' (означает запрос повышения прав UAC, если Python был установлен для всех пользователей) и 'force' (означает всегда запрашивать повышение прав).