5. Створення вбудованих дистрибутивів

Примітка

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

«Вбудований дистрибутив» — це те, що ви, ймовірно, звикли вважати «двійковим пакетом» або «інсталятором» (залежно від вашого досвіду). Однак він не обов’язково є двійковим, оскільки він може містити лише вихідний код Python та/або байт-код; і ми не називаємо це пакетом, тому що це слово вже вимовлено в Python. (А «інсталятор» — це термін, характерний для світу основних настільних систем.)

Вбудований дистрибутив – це те, як ви максимально полегшуєте життя інсталяторам вашого дистрибутива модуля: для користувачів систем Linux на основі RPM це двійковий RPM; для користувачів Windows це виконуваний інсталятор; для користувачів Linux на базі Debian це пакет Debian; і так далі. Очевидно, що ніхто не зможе створити вбудовані дистрибутиви для будь-якої платформи під сонцем, тому Distutils розроблено, щоб дозволити розробникам модулів зосередитися на своїй спеціальності — написанні коду та створенні вихідних дистрибутивів — тоді як проміжний вид, який називається packagers з’являється, щоб перетворити вихідні дистрибутиви на вбудовані дистрибутиви для стільки платформ, скільки пакувальників.

Звичайно, розробник модуля може бути власним пакувальником; або пакувальник може бути волонтером «десь там», який має доступ до платформи, якого не має оригінальний розробник; або це може бути програмне забезпечення, яке періодично збирає нові вихідні дистрибутиви та перетворює їх на вбудовані дистрибутиви для стількох платформ, до яких програмне забезпечення має доступ. Незалежно від того, ким вони є, пакетувальник використовує сценарій налаштування та сімейство команд 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; за замовчуванням створюються дурні дистрибутиви відносно 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

bzip-файл 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

wininst

self-extracting ZIP file for 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_wininst is deprecated since Python 3.8.

Примітка

bdist_msi is deprecated since 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>" \
                bdist_wininst --target-version="2.0"

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

Параметр або розділ файлу RPM .spec

Параметр сценарію налаштування Distutils

Ім’я

name

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

description

Версія

version

Продавець

author і author_email, або — & maintainer і maintainer_email

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

license

Url

url

%dопис (розділ)

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.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. Creating Windows Installers

Попередження

bdist_wininst is deprecated since Python 3.8.

Попередження

bdist_msi is deprecated since Python 3.9.

Executable installers are the natural format for binary distributions on Windows. They display a nice graphical user interface, display some information about the module distribution to be installed taken from the metadata in the setup script, let the user select a few options, and start or cancel the installation.

Since the metadata is taken from the setup script, creating Windows installers is usually as easy as running:

python setup.py bdist_wininst

or the bdist command with the --formats option:

python setup.py bdist --formats=wininst

If you have a pure module distribution (only containing pure Python modules and packages), the resulting installer will be version independent and have a name like foo-1.0.win32.exe. Note that creating wininst binary distributions in only supported on Windows systems.

If you have a non-pure distribution, the extensions can only be created on a Windows platform, and will be Python version dependent. The installer filename will reflect this and now has the form foo-1.0.win32-py2.0.exe. You have to create a separate installer for every Python version you want to support.

The installer will try to compile pure modules into bytecode after installation on the target system in normal and optimizing mode. If you don’t want this to happen for some reason, you can run the bdist_wininst command with the --no-target-compile and/or the --no-target-optimize option.

By default the installer will display the cool «Python Powered» logo when it is run, but you can also supply your own 152x261 bitmap which must be a Windows .bmp file with the --bitmap option.

The installer will also display a large title on the desktop background window when it is run, which is constructed from the name of your distribution and the version number. This can be changed to another text by using the --title option.

The installer file will be written to the «distribution directory» — normally dist/, but customizable with the --dist-dir option.

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

to build a 64bit version of your extension. The Windows Installers also support this option, so the command:

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 функції налаштування.

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

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

Деякі функції, особливо корисні в цьому контексті, доступні як додаткові вбудовані функції в сценарії встановлення.

directory_created(path)
file_created(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]]]])

Ця функція створює ярлик. ціль — це шлях до програми, яка запускається за допомогою ярлика. description — це опис ярлика. ім’я файлу – це назва ярлика, який побачить користувач. arguments визначає аргументи командного рядка, якщо такі є. workdir — це робочий каталог для програми. iconpath — це файл, що містить піктограму для ярлика, а iconindex — це індекс піктограми у файлі iconpath. Знову ж таки, для отримання детальної інформації зверніться до документації Microsoft для інтерфейсу IShellLink.

5.4. Vista User Access Control (UAC)

Starting with Python 2.6, bdist_wininst supports a --user-access-control option. The default is „none“ (meaning no UAC handling is done), and other valid values are „auto“ (meaning prompt for UAC elevation if Python was installed for all users) and „force“ (meaning always prompt for elevation).

Примітка

bdist_wininst is deprecated since Python 3.8.

Примітка

bdist_msi is deprecated since Python 3.9.