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

setupscript.md

434 строк · 43.2 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.6/distutils/setupscript.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 2. Написание сценария установки89Сценарий установки является центром всей деятельности по сборке, распространению и установке модулей с помощью Distutils. Основная цель сценария установки – описать ваш дистрибутив модулей для Distutils, чтобы различные команды, работающие с вашими модулями, делали правильные вещи. Как мы видели в разделе [A Simple Example](https://python-all.ru/3.6/distutils/introduction.html#distutils-simple-example) выше, сценарий установки состоит в основном из вызова `setup()`, и большая часть информации, передаваемой Distutils разработчиком модуля, передаётся в виде именованных аргументов `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.6/distutils/introduction.html#distutils-simple-example): больше метаданных и указание чистых модулей Python по пакетам, а не по модулям. Это важно, поскольку Distutils состоят из нескольких десятков модулей, разбитых (пока) на два пакета; явный список всех модулей было бы утомительно составлять и сложно поддерживать. Дополнительную информацию о метаданных см. в разделе [Additional meta-data](https://python-all.ru/3.6/distutils/setupscript.html#meta-data).2930Обратите внимание: любые пути (к файлам или каталогам), указанные в сценарии установки, должны записываться в стиле Unix, то есть с разделителем-слешем. Distutils позаботится о преобразовании этого платформонезависимого представления в то, что подходит для вашей текущей платформы, перед фактическим использованием пути. Это делает ваш сценарий установки переносимым между операционными системами, что, конечно, является одной из главных целей Distutils. В этом духе все пути в данном документе записываются через слеш.3132Это, конечно, относится только к путям, передаваемым функциям Distutils. Если вы, например, используете стандартные функции Python, такие как [`glob.glob()`](https://python-all.ru/3.6/library/glob.html#glob.glob) или [`os.listdir()`](https://python-all.ru/3.6/library/os.html#os.listdir) для указания файлов, будьте внимательны и пишите переносимый код вместо жёсткого кодирования разделителей пути: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.6/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```5657Запись `package: dir` в словаре `package_dir` неявно применяется ко всем пакетам ниже *пакета*, поэтому случай `foo.bar` обрабатывается автоматически. В этом примере наличие `packages = ['foo', 'foo.bar']` указывает Distutils искать `lib/__init__.py` и `lib/bar/__init__.py`. (Имейте в виду, что хотя `package_dir` применяется рекурсивно, необходимо явно перечислить все пакеты в `packages`: Distutils *не* будет рекурсивно сканировать дерево исходных текстов в поисках каталогов с файлом `__init__.py`.)5859## 2.2. Перечисление отдельных модулей6061Для небольшого дистрибутива модулей может быть удобнее перечислить все модули, а не пакеты – особенно случай одного модуля, который находится в «корневом пакете» (то есть вообще без пакета). Этот простейший случай был показан в разделе [Простой пример](https://python-all.ru/3.6/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.6/distutils/apiref.html#distutils.core.Extension), каждый из которых описывает один модуль расширения. Предположим, ваш дистрибутив содержит одно расширение с именем `foo`, реализованное в `foo.c`. Если не требуется дополнительных указаний компилятору/компоновщику, описание этого расширения довольно просто:7475```python76Extension('foo', ['foo.c'])77```7879Класс `Extension` можно импортировать из [`distutils.core`](https://python-all.ru/3.6/distutils/apiref.html#module-distutils.core) вместе с `setup()`. Таким образом, сценарий 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.6/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.6/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.6/distutils/apiref.html#distutils.core.Extension) помогут, если нужно указать каталоги включения для поиска или макросы препроцессора для определения/отмены: `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.) Поскольку каталог включения Python – `/usr/local/include/python1.5` в данном случае – всегда включён в путь поиска при сборке расширений Python, лучший подход – написать код на C так:166167```python168#include <Numerical/arrayobject.h>169```170171Если вам всё же нужно поместить каталог включения `Numerical` непосредственно в путь поиска заголовков, вы можете найти этот каталог с помощью модуля Distutils [`distutils.sysconfig`](https://python-all.ru/3.6/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` является логической; если она равна true, сбой сборки расширения не прервёт процесс сборки, а просто не приведёт к установке ошибочного расширения.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.6/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()`. Значение этого аргумента – список строк, каждая из которых указывает имя модуля или пакета и, опционально, версию. Если версия не указана, считается, что она совпадает с версией дистрибутива.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`) позволяет явно переопределить путь к интерпретатору.286287Опция `scripts` – это просто список файлов, которые обрабатываются таким образом. Из скрипта установки PyXML:288289```python290setup(...,291      scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']292      )293```294295Изменено в версии 3.1: Все скрипты также будут добавлены в файл `MANIFEST`, если не предоставлен шаблон. См. [Указание файлов для распространения](https://python-all.ru/3.6/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.6/distutils/sourcedist.html#manifest).330331## 2.7. Установка дополнительных файлов332333Опция `data_files` может использоваться для указания дополнительных файлов, необходимых для распространяемого модуля: файлов конфигурации, каталогов сообщений, файлов данных, всего, что не подходит под предыдущие категории.334335`data_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Каждая пара (*каталог*, *файлы*) в последовательности задаёт каталог установки и файлы для установки туда. Если *каталог* указан относительным путём, он интерпретируется относительно префикса установки (`sys.prefix` для пакетов на чистом Python, `sys.exec_prefix` для пакетов, содержащих модули расширения). Каждое имя файла из *файлы* интерпретируется относительно `setup.py`-скрипта, находящегося в корне дистрибутива исходного кода пакета. Информация о каталоге из *файлы* не используется для определения конечного положения устанавливаемого файла; используется только имя файла.348349Можно указать опцию `data_files` как простую последовательность файлов без указания целевого каталога, но это не рекомендуется, и команда **install** выведет предупреждение. Чтобы установить файлы данных непосредственно в целевой каталог, в качестве каталога нужно задать пустую строку.350351Изменено в версии 3.1: Все файлы, соответствующие `data_files`, будут добавлены в файл `MANIFEST`, если не предоставлен шаблон. См. [Указание файлов для распространения](https://python-all.ru/3.6/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| `platforms` | список платформ | список строк |  |371| `license` | лицензия для пакета | короткая строка | (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.6/distutils/setupscript.html).3795. Поле `long_description` используется PyPI при [регистрации](https://python-all.ru/3.6/distutils/packageindex.html#package-register) пакета, чтобы [создать его домашнюю страницу](https://python-all.ru/3.6/distutils/packageindex.html#package-display).3806. Поле `license` – это текст, указывающий лицензию, покрывающую пакет, если лицензия не выбрана из классификаторов Trove «License». См. поле `Classifier`. Обратите внимание, что существует опция распространения `licence`, которая устарела, но всё ещё является псевдонимом для `license`.381382**«короткая строка»**383384Одна строка текста, не более 200 символов.385386**«длинная строка»**387388Несколько строк обычного текста в формате reStructuredText (см. [http://docutils.sourceforge.net/](https://python-all.ru/3.6/distutils/setupscript.html)).389390**«список строк»**391392См. ниже.393394Кодирование информации о версии – само по себе искусство. Пакеты Python обычно придерживаются формата версии *major.minor\[.patch\]\[sub\]*. Основной номер (major) равен 0 для начальных экспериментальных выпусков ПО. Он увеличивается для выпусков, представляющих собой важные вехи в пакете. Дополнительный номер (minor) увеличивается, когда в пакет добавляются важные новые функции. Номер патча увеличивается при выпусках с исправлением ошибок. Иногда дополнительная информация о версии в конце используется для обозначения подвыпусков. Это «a1,a2,…,aN» (для альфа-версий, где функциональность и API могут меняться), «b1,b2,…,bN» (для бета-версий, которые только исправляют ошибки) и «pr1,pr2,…,prN» (для финального тестирования перед релизом). Некоторые примеры:395396**0.1.0**397398первый экспериментальный выпуск пакета399400**1.0.1a2**401402второй альфа-выпуск первой патч-версии 1.0403404`classifiers` задаются в списке Python:405406```python407setup(...,408      classifiers=[409          'Development Status :: 4 - Beta',410          'Environment :: Console',411          'Environment :: Web Environment',412          'Intended Audience :: End Users/Desktop',413          'Intended Audience :: Developers',414          'Intended Audience :: System Administrators',415          'License :: OSI Approved :: Python Software Foundation License',416          'Operating System :: MacOS :: MacOS X',417          'Operating System :: Microsoft :: Windows',418          'Operating System :: POSIX',419          'Programming Language :: Python',420          'Topic :: Communications :: Email',421          'Topic :: Office/Business',422          'Topic :: Software Development :: Bug Tracking',423          ],424      )425```426427## 2.9. Отладка скрипта установки428429Иногда что-то идет не так, и скрипт установки делает не то, что хочет разработчик.430431Distutils перехватывает любые исключения при запуске скрипта установки и выводит простое сообщение об ошибке перед завершением скрипта. Причина такого поведения – не запутывать администраторов, которые мало знают о Python и пытаются установить пакет. Если они получат длинную трассировку из глубин Distutils, они могут подумать, что пакет или установка Python сломаны, потому что не прочитают все до конца и не увидят, что проблема в правах доступа.432433С другой стороны, это не помогает разработчику найти причину сбоя. Для этой цели переменная окружения `DISTUTILS_DEBUG` может быть установлена в любое значение, кроме пустой строки, и distutils теперь будет выводить подробную информацию о том, что он делает, выводить полную трассировку при возникновении исключения и выводить всю командную строку при сбое внешней программы (например, компилятора C).434