setupscript.md
1> **Источник:** https://python-all.ru/3.4/distutils/setupscript.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 2. Написание сценария установки89The setup script is the centre of all activity in building, distributing, and installing modules using the Distutils. The main purpose of the setup script is to describe your module distribution to the Distutils, so that the various commands that operate on your modules do the right thing. As we saw in section [*A Simple Example*](https://python-all.ru/3.4/distutils/introduction.html#distutils-simple-example) above, the setup script consists mainly of a call to `setup()`, and most information supplied to the Distutils by the module developer is supplied as keyword arguments to `setup()`.1011Вот немного более сложный пример, который мы будем рассматривать в следующих нескольких разделах: собственный сценарий установки Distutils. (Имейте в виду, что хотя Distutils входят в состав Python 1.6 и более поздних версий, они также существуют независимо, чтобы пользователи Python 1.5.2 могли использовать их для установки других дистрибутивов модулей. Собственный сценарий установки Distutils, показанный здесь, используется для установки пакета в Python 1.5.2.)1213```python14#!/usr/bin/env python1516from distutils.core import setup1718setup(name='Distutils',19 version='1.0',20 description='Python Distribution Utilities',21 author='Greg Ward',22 author_email='gward@python.net',23 url='https://www.python.org/sigs/distutils-sig/',24 packages=['distutils', 'distutils.command'],25 )26```2728Есть только два отличия от тривиального однофайлового дистрибутива, представленного в разделе [*A Simple Example*](https://python-all.ru/3.4/distutils/introduction.html#distutils-simple-example): больше метаданных и указание чистых модулей Python по пакетам, а не по модулям. Это важно, поскольку Distutils состоят из нескольких десятков модулей, разбитых (пока) на два пакета; явный список всех модулей было бы утомительно составлять и сложно поддерживать. Дополнительную информацию о метаданных см. в разделе [*Additional meta-data*](https://python-all.ru/3.4/distutils/setupscript.html#meta-data).2930Обратите внимание: любые пути (к файлам или каталогам), указанные в сценарии установки, должны записываться в стиле Unix, то есть с разделителем-слешем. Distutils позаботится о преобразовании этого платформонезависимого представления в то, что подходит для вашей текущей платформы, перед фактическим использованием пути. Это делает ваш сценарий установки переносимым между операционными системами, что, конечно, является одной из главных целей Distutils. В этом духе все пути в данном документе записываются через слеш.3132This, of course, only applies to pathnames given to Distutils functions. If you, for example, use standard Python functions such as [`glob.glob()`](https://python-all.ru/3.4/library/glob.html#glob.glob) or [`os.listdir()`](https://python-all.ru/3.4/library/os.html#os.listdir) to specify files, you should be careful to write portable code instead of hardcoding path separators:3334```python35glob.glob(os.path.join('mydir', 'subdir', '*.html'))36os.listdir(os.path.join('mydir', 'subdir'))37```3839## 2.1. Перечисление целых пакетов4041Опция `packages` указывает Distutils обрабатывать (собирать, распространять, устанавливать и т.д.) все чистые модули Python, находящиеся в каждом пакете, упомянутом в списке `packages`. Для этого, разумеется, должно быть соответствие между именами пакетов и каталогами в файловой системе. Соответствие по умолчанию – самое очевидное: пакет [`distutils`](https://python-all.ru/3.4/library/distutils.html#module-distutils) находится в каталоге `distutils` относительно корня дистрибутива. Таким образом, когда в скрипте установки указано `packages = ['foo']`, вы обещаете, что Distutils найдёт файл `foo/__init__.py` (на вашей системе он может называться иначе, но идея понятна) относительно каталога, где находится скрипт установки. Если это обещание нарушить, Distutils выдаст предупреждение, но всё равно обработает «сломанный» пакет.4243Если вы используете другое соглашение для размещения исходного каталога, это не проблема: достаточно указать опцию `package_dir`, чтобы сообщить Distutils о вашем соглашении. Например, предположим, что весь исходный код Python находится в `lib`, так что модули «корневого пакета» (то есть не входящие ни в какой пакет) лежат в `lib`, модули пакета `foo` – в `lib/foo` и так далее. Тогда в скрипт установки нужно поместить4445```python46package_dir = {'': 'lib'}47```4849в ваш скрипт установки. Ключи этого словаря – имена пакетов, а пустое имя пакета означает корневой пакет. Значения – имена каталогов относительно корня дистрибутива. В этом случае, когда указано `packages = ['foo']`, вы обещаете, что существует файл `lib/foo/__init__.py`.5051Другое возможное соглашение – поместить пакет `foo` прямо в `lib`, пакет `foo.bar` – в `lib/bar` и т.д. В скрипте установки это будет записано как5253```python54package_dir = {'foo': 'lib'}55```5657A `package: dir` entry in the `package_dir` dictionary implicitly applies to all packages below *package*, so the `foo.bar` case is automatically handled here. In this example, having `packages = ['foo', 'foo.bar']` tells the Distutils to look for `lib/__init__.py` and `lib/bar/__init__.py`. (Keep in mind that although `package_dir` applies recursively, you must explicitly list all packages in `packages`: the Distutils will *not* recursively scan your source tree looking for any directory with an `__init__.py` file.)5859## 2.2. Перечисление отдельных модулей6061Для небольшого дистрибутива модулей может быть удобнее перечислить все модули, а не пакеты – особенно случай одного модуля, который находится в «корневом пакете» (то есть вообще без пакета). Этот простейший случай был показан в разделе [*Простой пример*](https://python-all.ru/3.4/distutils/introduction.html#distutils-simple-example); вот немного более сложный пример:6263```python64py_modules = ['mod1', 'pkg.mod2']65```6667Здесь описаны два модуля: один в «корневом» пакете, другой – в пакете `pkg`. Снова, соответствие «пакет/каталог» по умолчанию подразумевает, что эти два модуля находятся в `mod1.py` и `pkg/mod2.py`, а также существует `pkg/__init__.py`. И опять же, можно переопределить соответствие пакетов и каталогов с помощью опции `package_dir`.6869## 2.3. Описание модулей расширений7071Так же как написание модулей расширения Python немного сложнее, чем написание чистых модулей Python, их описание для Distutils тоже немного сложнее. В отличие от чистых модулей, недостаточно просто перечислить модули или пакеты и ожидать, что Distutils сам найдёт нужные файлы; необходимо указать имя расширения, исходные файлы и любые требования к компиляции/компоновке (каталоги включения, библиотеки для компоновки и т.д.).7273Всё это делается через ещё один именованный аргумент `setup()` – опцию `ext_modules`. `ext_modules` – это просто список экземпляров [`Extension`](https://python-all.ru/3.4/distutils/apiref.html#distutils.core.Extension), каждый из которых описывает отдельный модуль расширения. Предположим, ваш дистрибутив содержит одно расширение с именем `foo`, реализованное в `foo.c`. Если дополнительные инструкции компилятору/линковщику не нужны, описание этого расширения выглядит совсем просто:7475```python76Extension('foo', ['foo.c'])77```7879Класс `Extension` можно импортировать из [`distutils.core`](https://python-all.ru/3.4/distutils/apiref.html#module-distutils.core) вместе с `setup()`. Таким образом, скрипт установки для дистрибутива, содержащего только это одно расширение и ничего больше, может выглядеть так:8081```python82from distutils.core import setup, Extension83setup(name='foo',84 version='1.0',85 ext_modules=[Extension('foo', ['foo.c'])],86 )87```8889Класс `Extension` (фактически, лежащая в его основе механика сборки расширений, реализованная командой **build\_ext**) поддерживает большую гибкость при описании расширений Python, что объясняется в следующих разделах.9091### 2.3.1. Имена расширений и пакеты9293Первым аргументом конструктора [`Extension`](https://python-all.ru/3.4/distutils/apiref.html#distutils.core.Extension) всегда является имя расширения, включая любые имена пакетов. Например,9495```python96Extension('foo', ['src/foo1.c', 'src/foo2.c'])97```9899описывает расширение, находящееся в корневом пакете, тогда как100101```python102Extension('pkg.foo', ['src/foo1.c', 'src/foo2.c'])103```104105описывает то же расширение в пакете `pkg`. Исходные файлы и результирующий объектный код в обоих случаях идентичны; разница лишь в том, где в файловой системе (а следовательно, и в иерархии пространства имён Python) окажется результирующее расширение.106107Если у вас есть несколько расширений в одном пакете (или все под одной базовой группой), используйте именованный аргумент `ext_package` в `setup()`. Например,108109```python110setup(...,111 ext_package='pkg',112 ext_modules=[Extension('foo', ['foo.c']),113 Extension('subpkg.bar', ['bar.c'])],114 )115```116117скомпилирует `foo.c` в расширение `pkg.foo`, а `bar.c` – в `pkg.subpkg.bar`.118119### 2.3.2. Исходные файлы расширений120121Второй аргумент конструктора [`Extension`](https://python-all.ru/3.4/distutils/apiref.html#distutils.core.Extension) – это список исходных файлов. Поскольку Distutils в настоящее время поддерживают только расширения на C, C++ и Objective-C, это обычно файлы C/C++/Objective-C. (Используйте соответствующие расширения, чтобы различать файлы C++: `.cc` и `.cpp`, похоже, распознаются как компиляторами Unix, так и Windows.)122123Однако в список можно также включать файлы интерфейсов SWIG (`.i`); команда **build\_ext** умеет работать с расширениями SWIG: она запустит SWIG на файле интерфейса и скомпилирует полученный C/C++-файл в ваше расширение.124125Несмотря на это предупреждение, опции для SWIG в настоящее время можно передавать так:126127```python128setup(...,129 ext_modules=[Extension('_foo', ['foo.i'],130 swig_opts=['-modern', '-I../include'])],131 py_modules=['foo'],132 )133```134135Или в командной строке так:136137```python138> python setup.py build_ext --swig-opts="-modern -I../include"139```140141На некоторых платформах можно включать в расширение неисходные файлы, которые обрабатываются компилятором. В настоящее время это касается файлов сообщений Windows (`.mc`) и файлов определения ресурсов (`.rc`) для Visual C++. Они будут скомпилированы в двоичные ресурсные файлы (`.res`) и подключатся к исполняемому файлу.142143### 2.3.3. Параметры препроцессора144145Три необязательных аргумента [`Extension`](https://python-all.ru/3.4/distutils/apiref.html#distutils.core.Extension) помогут, если нужно указать каталоги для поиска include или макросы препроцессора для определения/отмены определения: `include_dirs`, `define_macros` и `undef_macros`.146147Например, если вашему расширению требуются заголовочные файлы из каталога `include` в корне дистрибутива, используйте опцию `include_dirs`:148149```python150Extension('foo', ['foo.c'], include_dirs=['include'])151```152153Там можно указывать абсолютные пути; если вы знаете, что ваше расширение будет собираться только в Unix-системах с установленным X11R6 в `/usr`, можно обойтись154155```python156Extension('foo', ['foo.c'], include_dirs=['/usr/include/X11'])157```158159Следует избегать такого непереносимого использования, если вы планируете распространять свой код: вероятно, лучше написать код на C так:160161```python162#include <X11/Xlib.h>163```164165Если нужно включить заголовочные файлы из какого-либо другого расширения Python, можно воспользоваться тем, что заголовочные файлы устанавливаются единообразно командой Distutils **install\_headers**. Например, заголовочные файлы Numerical Python устанавливаются (в стандартной установке Unix) в `/usr/local/include/python1.5/Numerical`. (Точное расположение будет различаться в зависимости от платформы и установки Python.) Поскольку каталог include Python – `/usr/local/include/python1.5` в данном случае – всегда включается в путь поиска при сборке расширений Python, лучший подход – писать C-код так:166167```python168#include <Numerical/arrayobject.h>169```170171Если же необходимо поместить каталог include `Numerical` прямо в путь поиска заголовков, то этот каталог можно найти с помощью модуля Distutils [`distutils.sysconfig`](https://python-all.ru/3.4/distutils/apiref.html#module-distutils.sysconfig):172173```python174from distutils.sysconfig import get_python_inc175incdir = os.path.join(get_python_inc(plat_specific=1), 'Numerical')176setup(...,177 Extension(..., include_dirs=[incdir]),178 )179```180181Несмотря на то, что это вполне переносимо – будет работать в любой установке Python, независимо от платформы, – вероятно, проще просто написать код на C разумным способом.182183Можно определять и отменять макросы препроцессора с помощью опций `define_macros` и `undef_macros`. `define_macros` принимает список кортежей `(name, value)`, где `name` – имя определяемого макроса (строка), а `value` – его значение: строка или `None`. (Определение макроса `FOO` как `None` эквивалентно голому `#define FOO` в C-исходнике: для большинства компиляторов это устанавливает `FOO` в строку `1`.) `undef_macros` – это просто список макросов, которые нужно отменить.184185Например:186187```python188Extension(...,189 define_macros=[('NDEBUG', '1'),190 ('HAVE_STRFTIME', None)],191 undef_macros=['HAVE_FOO', 'HAVE_BAR'])192```193194is the equivalent of having this at the top of every C source file:195196```python197#define NDEBUG 1198#define HAVE_STRFTIME199#undef HAVE_FOO200#undef HAVE_BAR201```202203### 2.3.4. Параметры библиотек204205Также можно указать библиотеки, с которыми нужно линковать расширение, и каталоги для поиска этих библиотек. Опция `libraries` – это список библиотек для линковки, `library_dirs` – список каталогов для поиска библиотек на этапе линковки, а `runtime_library_dirs` – список каталогов для поиска разделяемых (динамически загружаемых) библиотек во время выполнения.206207Например, если требуется скомпоновать расширение с библиотеками, которые заведомо находятся в стандартном пути поиска библиотек в целевых системах,208209```python210Extension(...,211 libraries=['gdbm', 'readline'])212```213214Если нужно линковаться с библиотеками в нестандартном расположении, придётся указать это расположение в `library_dirs`:215216```python217Extension(...,218 library_dirs=['/usr/X11R6/lib'],219 libraries=['X11', 'Xt'])220```221222(Повторим: подобные непереносимые конструкции следует избегать, если планируется распространять свой код.)223224### 2.3.5. Прочие параметры225226Существуют и другие опции, которые можно использовать для обработки особых случаев.227228Опция `optional` – логическая; если она истинна, то сбой сборки расширения не прервёт процесс сборки, а просто не установит отказавшее расширение.229230Опция `extra_objects` – это список объектных файлов, передаваемых линковщику. Эти файлы не должны иметь расширений, так как используется расширение по умолчанию для компилятора.231232`extra_compile_args` и `extra_link_args` можно использовать для указания дополнительных параметров командной строки для соответствующих команд компилятора и линковщика.233234`export_symbols` имеет смысл только в Windows. Он может содержать список символов (функций или переменных), которые нужно экспортировать. Эта опция не нужна при сборке скомпилированных расширений: Distutils автоматически добавит `initmodule` в список экспортируемых символов.235236Опция `depends` – это список файлов, от которых зависит расширение (например, заголовочные файлы). Команда сборки вызовет компилятор для исходников, чтобы пересобрать расширение, если какой-либо из этих файлов изменился после предыдущей сборки.237238## 2.4. Соотношения между дистрибутивами и пакетами239240Дистрибутив может относиться к пакетам тремя определёнными способами:2412421. Он может требовать пакеты или модули.2432. Он может предоставлять пакеты или модули.2443. Он может заменять (делать устаревшими) пакеты или модули.245246Эти зависимости можно указать с помощью именованных аргументов функции [`distutils.core.setup()`](https://python-all.ru/3.4/distutils/apiref.html#distutils.core.setup).247248Зависимости от других модулей и пакетов Python можно указать, передав *requires* в качестве именованного аргумента функции `setup()`. Значением должен быть список строк. Каждая строка задает требуемый пакет и, опционально, подходящие версии.249250Чтобы указать, что требуется любая версия модуля или пакета, строка должна состоять только из имени модуля или пакета. Примеры: `'mymodule'` и `'xml.parsers.expat'`.251252Если требуются конкретные версии, можно указать последовательность квалификаторов в скобках. Каждый квалификатор может состоять из оператора сравнения и номера версии. Допустимые операторы сравнения:253254```python255< > ==256<= >= !=257```258259Их можно комбинировать, используя несколько квалификаторов, разделённых запятыми (и необязательными пробелами). В этом случае все квалификаторы должны совпадать; используется логическое И для объединения результатов.260261Рассмотрим несколько примеров:262263| Выражение Requires | Пояснение |264| --- | --- |265| `==1.0` | Совместима только версия `1.0` |266| `>1.0, !=1.5.1, <2.0` | Любая версия после `1.0` и до `2.0` совместима, за исключением `1.5.1` |267268Теперь, когда мы можем указывать зависимости, нужно также уметь указывать, что мы предоставляем, чтобы другие дистрибутивы могли на это ссылаться. Для этого используется именованный аргумент *provides* функции `setup()`. Значением этого аргумента является список строк, каждая из которых задает имя модуля или пакета Python и, опционально, версию. Если версия не указана, считается, что она соответствует версии дистрибутива.269270Несколько примеров:271272| Выражение Provides | Пояснение |273| --- | --- |274| `mypkg` | Предоставляет `mypkg`, используя версию дистрибутива |275| `mypkg (1.1)` | Предоставляет `mypkg` версии 1.1, независимо от версии дистрибутива |276277Пакет может объявлять, что он заменяет (делает устаревшими) другие пакеты, с помощью именованного аргумента *obsoletes*. Его значение аналогично значению аргумента *requires*: список строк, задающих спецификаторы модуля или пакета. Каждый спецификатор состоит из имени модуля или пакета, за которым необязательно следуют один или несколько квалификаторов версии. Версионные квалификаторы указываются в скобках после имени модуля или пакета.278279Версии, указанные квалификаторами, считаются заменяемыми (устаревшими) данным дистрибутивом. Если квалификаторы не указаны, считаются устаревшими все версии указанного модуля или пакета.280281## 2.5. Установка сценариев282283До сих пор мы имели дело с чистыми и нечистыми модулями Python, которые обычно не запускаются сами по себе, а импортируются скриптами.284285Скрипты – это файлы, содержащие исходный код Python, предназначенные для запуска из командной строки. Скрипты не требуют от Distutils выполнения сложных действий. Единственная умная особенность: если первая строка скрипта начинается с `#!` и содержит слово «python», Distutils скорректирует первую строку, чтобы она указывала на текущее местоположение интерпретатора. По умолчанию она заменяется на текущее местоположение интерпретатора. Опция *--executable* (или [*-e*](https://python-all.ru/3.4/library/tarfile.html#cmdoption-e)) позволяет явно переопределить путь к интерпретатору.286287Опция `scripts` – это просто список файлов, которые обрабатываются таким образом. Например, из скрипта setup PyXML:288289```python290setup(...,291 scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']292 )293```294295Изменено в версии 3.1: Все скрипты также будут добавлены в файл `MANIFEST`, если не указан шаблон. См. [*Указание файлов для распространения*](https://python-all.ru/3.4/distutils/sourcedist.html#manifest).296297## 2.6. Установка данных пакетов298299Часто в пакет нужно установить дополнительные файлы. Эти файлы – обычно данные, тесно связанные с реализацией пакета, или текстовые файлы с документацией, которая может быть полезна программистам, использующим пакет. Такие файлы называются *данными пакета*.300301Данные пакета можно добавить, используя именованный аргумент `package_data` функции `setup()`. Значение должно быть словарем, сопоставляющим имя пакета со списком относительных путей к файлам, которые должны быть скопированы в пакет. Пути интерпретируются относительно каталога, содержащего пакет (если уместно, используется информация из словаря `package_dir`); то есть файлы должны быть частью пакета в исходных каталогах. Они также могут содержать шаблоны glob.302303Имена путей могут содержать части каталогов; все необходимые каталоги будут созданы при установке.304305Например, если пакет должен содержать подкаталог с несколькими файлами данных, файлы можно расположить в дереве исходников следующим образом:306307```python308setup.py309src/310 mypkg/311 __init__.py312 module.py313 data/314 tables.dat315 spoons.dat316 forks.dat317```318319Соответствующий вызов `setup()` может выглядеть так:320321```python322setup(...,323 packages=['mypkg'],324 package_dir={'mypkg': 'src/mypkg'},325 package_data={'mypkg': ['data/*.dat']},326 )327```328329Изменено в версии 3.1: Все файлы, соответствующие условиям `package_data`, будут добавлены в файл `MANIFEST`, если не указан шаблон. См. [*Указание файлов для распространения*](https://python-all.ru/3.4/distutils/sourcedist.html#manifest).330331## 2.7. Установка дополнительных файлов332333Опция `data_files` может использоваться для указания дополнительных файлов, необходимых для распространения модуля: файлов конфигурации, каталогов сообщений, файлов данных – всего, что не вписывается в предыдущие категории.334335`data_files` задает последовательность пар (*directory*, *files*) следующим образом:336337```python338setup(...,339 data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),340 ('config', ['cfg/data.cfg']),341 ('/etc/init.d', ['init-script'])]342 )343```344345Обратите внимание: можно указать имена каталогов, в которые будут установлены файлы данных, но сами файлы переименовать нельзя.346347Каждая пара (*directory*, *files*) в последовательности задает каталог установки и файлы для установки в нем. Если *directory* – относительный путь, он интерпретируется относительно префикса установки (`sys.prefix` для чисто Python-пакетов, `sys.exec_prefix` для пакетов, содержащих расширения). Каждый файл в *files* интерпретируется относительно скрипта `setup.py` из корня пакета исходного кода. Информация о каталоге из *files* не используется для определения конечного расположения устанавливаемого файла; используется только имя файла.348349Можно указать опцию `data_files` как простой список файлов без указания целевого каталога, но это не рекомендуется, и команда **install** в этом случае выдаст предупреждение. Чтобы установить файлы данных непосредственно в целевой каталог, в качестве каталога следует указать пустую строку.350351Изменено в версии 3.1: Все файлы, соответствующие `data_files`, будут добавлены в файл `MANIFEST`, если не указан шаблон. См. [*Указание файлов для распространения*](https://python-all.ru/3.4/distutils/sourcedist.html#manifest).352353## 2.8. Дополнительные метаданные354355Скрипт setup может включать дополнительные метаданные помимо имени и версии. Эта информация включает:356357| Метаданные | Описание | Значение | Примечания |358| --- | --- | --- | --- |359| `name` | имя пакета | короткая строка | (1) |360| `version` | версия этого релиза | короткая строка | (1)(2) |361| `author` | имя автора пакета | короткая строка | (3) |362| `author_email` | адрес электронной почты автора пакета | адрес электронной почты | (3) |363| `maintainer` | имя сопровождающего пакета | короткая строка | (3) |364| `maintainer_email` | адрес электронной почты сопровождающего пакет | адрес электронной почты | (3) |365| `url` | домашняя страница пакета | URL | (1) |366| `description` | краткое описание пакета | короткая строка | |367| `long_description` | подробное описание пакета | длинная строка | (5) |368| `download_url` | расположение, откуда можно загрузить пакет | URL | (4) |369| `classifiers` | список классификаторов | список строк | (4) |370| `платформы` | список платформ | список строк | |371| `лицензия` | лицензия для пакета | короткая строка | (6) |372373Примечания:3743751. Эти поля обязательны.3762. Рекомендуется, чтобы версии имели формат *major.minor\[.patch\[.sub\]\]*.3773. Должен быть указан либо автор, либо сопровождающий. Если сопровождающий указан, distutils указывает его как автора в `PKG-INFO`.3784. Эти поля не следует использовать, если пакет должен быть совместим с версиями Python до 2.2.3 или 2.3. Список доступен на [сайте PyPI](https://python-all.ru/3.4/distutils/setupscript.html).3795. Поле `long_description` используется PyPI при [*регистрации*](https://python-all.ru/3.4/distutils/packageindex.html#package-register) пакета, чтобы [*построить его домашнюю страницу*](https://python-all.ru/3.4/distutils/packageindex.html#package-display).3806. Поле `license` представляет собой текст, указывающий лицензию, покрывающую пакет, когда лицензия не выбрана из классификаторов Trove «License». См. поле `Classifier`. Обратите внимание, что опция распространения `licence` устарела, но всё ещё действует как псевдоним для `license`.381382**«короткая строка»**383384Одна строка текста, не более 200 символов.385386**«длинная строка»**387388Несколько строк обычного текста в формате reStructuredText (см.389390[http://docutils.sourceforge.net/](https://python-all.ru/3.4/distutils/setupscript.html)391392).393394**«список строк»**395396См. ниже.397398Указание версии – это искусство само по себе. Пакеты Python обычно следуют формату версии *major.minor\[.patch\]\[sub\]*. Основной номер равен 0 для начальных экспериментальных выпусков ПО. Он увеличивается для выпусков, представляющих важные вехи в пакете. Второстепенный номер увеличивается, когда добавляются важные новые функции. Номер патча увеличивается при выпусках с исправлениями ошибок. Дополнительная завершающая информация о версии иногда используется для обозначения подвыпусков. Это «a1,a2,...,aN» (для альфа-выпусков, где функциональность и API могут измениться), «b1,b2,...,bN» (для бета-выпусков, которые только исправляют ошибки) и «pr1,pr2,...,prN» (для финального предрелизного тестирования). Некоторые примеры:399400**0.1.0**401402первый экспериментальный выпуск пакета403404**1.0.1a2**405406второй альфа-выпуск первой патч-версии 1.0407408`Классификаторы` задаются в виде списка Python:409410```python411setup(...,412 classifiers=[413 'Development Status :: 4 - Beta',414 'Environment :: Console',415 'Environment :: Web Environment',416 'Intended Audience :: End Users/Desktop',417 'Intended Audience :: Developers',418 'Intended Audience :: System Administrators',419 'License :: OSI Approved :: Python Software Foundation License',420 'Operating System :: MacOS :: MacOS X',421 'Operating System :: Microsoft :: Windows',422 'Operating System :: POSIX',423 'Programming Language :: Python',424 'Topic :: Communications :: Email',425 'Topic :: Office/Business',426 'Topic :: Software Development :: Bug Tracking',427 ],428 )429```430431## 2.9. Отладка сценария установки432433Иногда что-то идет не так, и скрипт установки делает не то, что хочет разработчик.434435Distutils перехватывает любые исключения при запуске скрипта установки и выводит простое сообщение об ошибке перед завершением скрипта. Причина такого поведения – не запутывать администраторов, которые мало знают о Python и пытаются установить пакет. Если они получат длинную трассировку из глубин Distutils, они могут подумать, что пакет или установка Python сломаны, потому что не прочитают все до конца и не увидят, что проблема в правах доступа.436437С другой стороны, это не помогает разработчику найти причину сбоя. Для этой цели можно установить переменную окружения `DISTUTILS_DEBUG` в любое значение, кроме пустой строки, и distutils будет выводить подробную информацию о своих действиях, полную трассировку при возникновении исключения, а также полную командную строку при сбое внешней программы (например, компилятора C).438