setupscript.md
1> **Источник:** https://python-all.ru/3.3/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.3/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='http://www.python.org/sigs/distutils-sig/',24 packages=['distutils', 'distutils.command'],25 )26```2728Есть только два отличия от тривиального однофайлового дистрибутива, представленного в разделе [*A Simple Example*](https://python-all.ru/3.3/distutils/introduction.html#distutils-simple-example): больше метаданных и указание чистых модулей Python по пакетам, а не по модулям. Это важно, поскольку Distutils состоят из нескольких десятков модулей, разбитых (пока) на два пакета; явный список всех модулей было бы утомительно составлять и сложно поддерживать. Дополнительную информацию о метаданных см. в разделе [*Additional meta-data*](https://python-all.ru/3.3/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.3/library/glob.html#glob.glob) or [`os.listdir()`](https://python-all.ru/3.3/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.3/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* неявно применяется ко всем пакетам, находящимся внутри *package*, поэтому случай с `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.3/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.3/distutils/apiref.html#distutils.core.Extension), каждый из которых описывает одно расширение. Предположим, дистрибутив включает одно расширение с именем `foo`, реализованное в файле `foo.c`. Если компилятору/компоновщику не нужны дополнительные инструкции, описание этого расширения выглядит очень просто:7475```python76Extension('foo', ['foo.c'])77```7879Класс `Extension` можно импортировать из [`distutils.core`](https://python-all.ru/3.3/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.3/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.3/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.3/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.3/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.3/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*) позволяет явно переопределить путь к интерпретатору.286287Параметр *scripts* – это просто список файлов, которые будут обработаны таким образом. Из сценария установки PyXML:288289```python290setup(...,291 scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']292 )293```294295Изменено в версии 3.1: Все скрипты также будут добавлены в файл `MANIFEST`, если не указан шаблон. См. [*Указание файлов для распространения*](https://python-all.ru/3.3/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.3/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.3/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.3/distutils/setupscript.html).3795. Поле `long_description` используется PyPI при [*регистрации*](https://python-all.ru/3.3/distutils/packageindex.html#package-register) пакета, чтобы [*построить его домашнюю страницу*](https://python-all.ru/3.3/distutils/packageindex.html#package-display).3806. Поле `license` представляет собой текст, указывающий лицензию, покрывающую пакет, когда лицензия не выбрана из классификаторов Trove «License». См. поле `Classifier`. Обратите внимание, что опция распространения `licence` устарела, но всё ещё действует как псевдоним для `license`.381382**«короткая строка»**383384Одна строка текста, не более 200 символов.385386**«длинная строка»**387388Многострочный простой текст в формате reStructuredText (см.389390[http://docutils.sf.net/](https://python-all.ru/3.3/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Если требуется включить классификаторы в файл `setup.py` и при этом сохранить обратную совместимость с версиями Python до 2.2.3, то можно добавить следующий фрагмент кода в `setup.py` перед вызовом `setup()`.432433```python434# исправить distutils, если он не справляется с ключевыми словами "classifiers" или435# ключевые слова "download_url"436from sys import version437if version < '2.2.3':438 from distutils.dist import DistributionMetadata439 DistributionMetadata.classifiers = None440 DistributionMetadata.download_url = None441```442443## 2.9. Отладка сценария установки444445Иногда что-то идет не так, и скрипт установки делает не то, что хочет разработчик.446447Distutils перехватывает любые исключения при запуске скрипта установки и выводит простое сообщение об ошибке перед завершением скрипта. Причина такого поведения – не запутывать администраторов, которые мало знают о Python и пытаются установить пакет. Если они получат длинную трассировку из глубин Distutils, они могут подумать, что пакет или установка Python сломаны, потому что не прочитают все до конца и не увидят, что проблема в правах доступа.448449С другой стороны, это не помогает разработчику найти причину сбоя. Для этой цели можно установить переменную окружения `DISTUTILS_DEBUG` в любое значение, кроме пустой строки, и distutils будет выводить подробную информацию о своих действиях, полную трассировку при возникновении исключения, а также полную командную строку при сбое внешней программы (например, компилятора C).450