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

setupscript.md

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

1> **Источник:** https://python-all.ru/3.10/distutils/setupscript.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 2. Написание сценария установки89> **Примечание**10>11> Этот документ сохраняется только до тех пор, пока `setuptools` документация по адресу [https://setuptools.readthedocs.io/en/latest/setuptools.html](https://python-all.ru/3.10/distutils/setupscript.html) не станет самостоятельно охватывать всю актуальную информацию, приведённую здесь.1213Сценарий установки является центром всей деятельности по сборке, распространению и установке модулей с помощью Distutils. Основная цель сценария установки – описать ваш дистрибутив модулей для Distutils, чтобы различные команды, работающие с вашими модулями, делали правильные вещи. Как мы видели в разделе [A Simple Example](https://python-all.ru/3.10/distutils/introduction.html#distutils-simple-example) выше, сценарий установки состоит в основном из вызова `setup()`, и большая часть информации, передаваемой Distutils разработчиком модуля, передаётся в виде именованных аргументов `setup()`.1415Вот немного более сложный пример, который мы будем рассматривать в следующих нескольких разделах: собственный сценарий установки Distutils. (Имейте в виду, что хотя Distutils входят в состав Python 1.6 и более поздних версий, они также существуют независимо, чтобы пользователи Python 1.5.2 могли использовать их для установки других дистрибутивов модулей. Собственный сценарий установки Distutils, показанный здесь, используется для установки пакета в Python 1.5.2.)1617```python18#!/usr/bin/env python1920from distutils.core import setup2122setup(name='Distutils',23      version='1.0',24      description='Python Distribution Utilities',25      author='Greg Ward',26      author_email='gward@python.net',27      url='https://www.python.org/sigs/distutils-sig/',28      packages=['distutils', 'distutils.command'],29     )30```3132Есть только два отличия от тривиального однофайлового дистрибутива, представленного в разделе [A Simple Example](https://python-all.ru/3.10/distutils/introduction.html#distutils-simple-example): больше метаданных и указание чистых модулей Python по пакетам, а не по модулям. Это важно, поскольку Distutils состоят из нескольких десятков модулей, разбитых (пока) на два пакета; явный список всех модулей было бы утомительно составлять и сложно поддерживать. Дополнительную информацию о метаданных см. в разделе [Additional meta-data](https://python-all.ru/3.10/distutils/setupscript.html#meta-data).3334Обратите внимание: любые пути (к файлам или каталогам), указанные в сценарии установки, должны записываться в стиле Unix, то есть с разделителем-слешем. Distutils позаботится о преобразовании этого платформонезависимого представления в то, что подходит для вашей текущей платформы, перед фактическим использованием пути. Это делает ваш сценарий установки переносимым между операционными системами, что, конечно, является одной из главных целей Distutils. В этом духе все пути в данном документе записываются через слеш.3536Это, конечно, относится только к путям, передаваемым функциям Distutils. Если вы, например, используете стандартные функции Python, такие как [`glob.glob()`](https://python-all.ru/3.10/library/glob.html#glob.glob) или [`os.listdir()`](https://python-all.ru/3.10/library/os.html#os.listdir) для указания файлов, будьте внимательны и пишите переносимый код вместо жёсткого кодирования разделителей пути:3738```python39glob.glob(os.path.join('mydir', 'subdir', '*.html'))40os.listdir(os.path.join('mydir', 'subdir'))41```4243## 2.1. Перечисление целых пакетов4445Опция `packages` указывает Distutils обрабатывать (собирать, распространять, устанавливать и т. д.) все чистые модули Python, найденные в каждом пакете, упомянутом в списке `packages`. Для этого, конечно, должно быть соответствие между именами пакетов и каталогами в файловой системе. Соответствие по умолчанию – самое очевидное: пакет [`distutils`](https://python-all.ru/3.10/library/distutils.html#module-distutils) находится в каталоге `distutils` относительно корня дистрибутива. Таким образом, когда вы пишете `packages = ['foo']` в своём сценарии установки, вы обещаете, что Distutils найдёт файл `foo/__init__.py` (название может отличаться в вашей системе, но идея понятна) относительно каталога, где находится ваш сценарий установки. Если вы нарушите это обещание, Distutils выдаст предупреждение, но всё равно обработает проблемный пакет.4647Если вы используете другую конвенцию для организации исходного каталога, это не проблема: нужно просто указать опцию `package_dir`, чтобы сообщить Distutils о вашей конвенции. Например, предположим, что вы храните все исходники Python в `lib`, так что модули в «корневом пакете» (т. е. не входящие ни в какой пакет) находятся в `lib`, модули пакета `foo` – в `lib/foo`, и так далее. Тогда вы укажете4849```python50package_dir = {'': 'lib'}51```5253в своём сценарии установки. Ключами этого словаря являются имена пакетов, а пустое имя пакета означает корневой пакет. Значения – имена каталогов относительно корня вашего дистрибутива. В этом случае, когда вы пишете `packages = ['foo']`, вы обещаете, что файл `lib/foo/__init__.py` существует.5455Другая возможная конвенция – поместить пакет `foo` прямо в `lib`, пакет `foo.bar` в `lib/bar`, и т. д. Это можно записать в сценарии установки как5657```python58package_dir = {'foo': 'lib'}59```6061Запись `package: dir` в словаре `package_dir` неявно применяется ко всем пакетам ниже *пакета*, поэтому случай `foo.bar` обрабатывается автоматически. В этом примере наличие `packages = ['foo', 'foo.bar']` указывает Distutils искать `lib/__init__.py` и `lib/bar/__init__.py`. (Имейте в виду, что хотя `package_dir` применяется рекурсивно, необходимо явно перечислить все пакеты в `packages`: Distutils *не* будет рекурсивно сканировать дерево исходных текстов в поисках каталогов с файлом `__init__.py`.)6263## 2.2. Перечисление отдельных модулей6465Для небольшого дистрибутива модулей может быть удобнее перечислить все модули, а не пакеты – особенно случай одного модуля, который находится в «корневом пакете» (то есть вообще без пакета). Этот простейший случай был показан в разделе [Простой пример](https://python-all.ru/3.10/distutils/introduction.html#distutils-simple-example); вот немного более сложный пример:6667```python68py_modules = ['mod1', 'pkg.mod2']69```7071Здесь описываются два модуля: один в «корневом» пакете, другой – в пакете `pkg`. По умолчанию соответствие пакетов и каталогов подразумевает, что эти два модуля находятся в `mod1.py` и `pkg/mod2.py`, а также существует `pkg/__init__.py`. И снова можно переопределить соответствие пакетов и каталогов с помощью опции `package_dir`.7273## 2.3. Описание модулей расширения7475Так же как написание модулей расширения Python немного сложнее, чем написание чистых модулей Python, их описание для Distutils тоже немного сложнее. В отличие от чистых модулей, недостаточно просто перечислить модули или пакеты и ожидать, что Distutils сам найдёт нужные файлы; необходимо указать имя расширения, исходные файлы и любые требования к компиляции/компоновке (каталоги включения, библиотеки для компоновки и т.д.).7677Все это делается через ещё один именованный аргумент для `setup()` – опцию `ext_modules`. `ext_modules` – это просто список экземпляров [`Extension`](https://python-all.ru/3.10/distutils/apiref.html#distutils.core.Extension), каждый из которых описывает один модуль расширения. Предположим, ваш дистрибутив содержит одно расширение с именем `foo`, реализованное в `foo.c`. Если не требуется дополнительных указаний компилятору/компоновщику, описание этого расширения довольно просто:7879```python80Extension('foo', ['foo.c'])81```8283Класс `Extension` можно импортировать из [`distutils.core`](https://python-all.ru/3.10/distutils/apiref.html#module-distutils.core) вместе с `setup()`. Таким образом, сценарий setup для дистрибутива модуля, содержащего только это одно расширение и ничего больше, может выглядеть так:8485```python86from distutils.core import setup, Extension87setup(name='foo',88      version='1.0',89      ext_modules=[Extension('foo', ['foo.c'])],90      )91```9293Класс `Extension` (точнее, лежащий в основе механизм сборки расширений, реализованный командой **build\_ext**) обеспечивает большую гибкость при описании расширений Python, что объясняется в следующих разделах.9495### 2.3.1. Имена расширений и пакеты9697Первым аргументом конструктора [`Extension`](https://python-all.ru/3.10/distutils/apiref.html#distutils.core.Extension) всегда является имя расширения, включая любые имена пакетов. Например,9899```python100Extension('foo', ['src/foo1.c', 'src/foo2.c'])101```102103описывает расширение, находящееся в корневом пакете, тогда как104105```python106Extension('pkg.foo', ['src/foo1.c', 'src/foo2.c'])107```108109описывает то же расширение в пакете `pkg`. Исходные файлы и результирующий объектный код в обоих случаях идентичны; разница лишь в том, где в файловой системе (а следовательно, где в иерархии пространств имён Python) находится результирующее расширение.110111Если у вас есть несколько расширений в одном пакете (или все под одним базовым пакетом), используйте именованный аргумент `ext_package` для `setup()`. Например,112113```python114setup(...,115      ext_package='pkg',116      ext_modules=[Extension('foo', ['foo.c']),117                   Extension('subpkg.bar', ['bar.c'])],118     )119```120121скомпилирует `foo.c` в расширение `pkg.foo`, а `bar.c` – в `pkg.subpkg.bar`.122123### 2.3.2. Исходные файлы расширения124125Второй аргумент конструктора [`Extension`](https://python-all.ru/3.10/distutils/apiref.html#distutils.core.Extension) – это список исходных файлов. Поскольку Distutils в настоящее время поддерживает только расширения на C, C++ и Objective-C, это обычно исходные файлы на C/C++/Objective-C. (Не забудьте использовать соответствующие расширения для файлов C++: `.cc` и `.cpp`, похоже, распознаются компиляторами как Unix, так и Windows.)126127Однако вы также можете включить в список файлы интерфейсов SWIG (`.i`); команда **build\_ext** умеет работать с расширениями SWIG: она запускает SWIG для файла интерфейса и компилирует полученный C/C++ файл в ваше расширение.128129Несмотря на это предупреждение, опции для SWIG в настоящее время можно передавать так:130131```python132setup(...,133      ext_modules=[Extension('_foo', ['foo.i'],134                             swig_opts=['-modern', '-I../include'])],135      py_modules=['foo'],136     )137```138139Или в командной строке так:140141```python142> python setup.py build_ext --swig-opts="-modern -I../include"143```144145На некоторых платформах можно включать неисходные файлы, которые обрабатываются компилятором и включаются в ваше расширение. В настоящее время это относится только к файлам текстов сообщений Windows (`.mc`) и файлам определения ресурсов (`.rc`) для Visual C++. Они будут скомпилированы в двоичные файлы ресурсов (`.res`) и слинкованы в исполняемый файл.146147### 2.3.3. Опции препроцессора148149Три необязательных аргумента для [`Extension`](https://python-all.ru/3.10/distutils/apiref.html#distutils.core.Extension) помогут, если нужно указать каталоги включения для поиска или макросы препроцессора для определения/отмены: `include_dirs`, `define_macros` и `undef_macros`.150151Например, если вашему расширению требуются заголовочные файлы в каталоге `include` в корне вашего дистрибутива, используйте опцию `include_dirs`:152153```python154Extension('foo', ['foo.c'], include_dirs=['include'])155```156157Там можно указать абсолютные пути; если вы знаете, что ваше расширение будет собираться только на Unix-системах с X11R6, установленным в `/usr`, можно обойтись158159```python160Extension('foo', ['foo.c'], include_dirs=['/usr/include/X11'])161```162163Следует избегать такого непереносимого использования, если вы планируете распространять свой код: вероятно, лучше написать код на C так:164165```python166#include <X11/Xlib.h>167```168169Если вам нужно включить заголовочные файлы из другого расширения Python, можно воспользоваться тем, что заголовочные файлы устанавливаются согласованным образом командой Distutils **install\_headers**. Например, заголовочные файлы Numerical Python устанавливаются (в стандартной установке Unix) в `/usr/local/include/python1.5/Numerical`. (Точное расположение будет различаться в зависимости от платформы и установки Python.) Поскольку каталог включения Python – `/usr/local/include/python1.5` в данном случае – всегда включён в путь поиска при сборке расширений Python, лучший подход – написать код на C так:170171```python172#include <Numerical/arrayobject.h>173```174175Если вам всё же нужно поместить каталог включения `Numerical` непосредственно в путь поиска заголовков, вы можете найти этот каталог с помощью модуля Distutils [`distutils.sysconfig`](https://python-all.ru/3.10/distutils/apiref.html#module-distutils.sysconfig):176177```python178from distutils.sysconfig import get_python_inc179incdir = os.path.join(get_python_inc(plat_specific=1), 'Numerical')180setup(...,181      Extension(..., include_dirs=[incdir]),182      )183```184185Несмотря на то, что это вполне переносимо – будет работать в любой установке Python, независимо от платформы, – вероятно, проще просто написать код на C разумным способом.186187Можно определять и отменять макросы препроцессора с помощью опций `define_macros` и `undef_macros`. `define_macros` принимает список кортежей `(name, value)`, где `name` – имя определяемого макроса (строка), а `value` – его значение: строка или `None`. (Определение макроса `FOO` как `None` эквивалентно простому `#define FOO` в исходном коде C: в большинстве компиляторов это устанавливает `FOO` в строку `1`.) `undef_macros` – это просто список макросов для отмены.188189Например:190191```python192Extension(...,193          define_macros=[('NDEBUG', '1'),194                         ('HAVE_STRFTIME', None)],195          undef_macros=['HAVE_FOO', 'HAVE_BAR'])196```197198is the equivalent of having this at the top of every C source file:199200```python201#define NDEBUG 1202#define HAVE_STRFTIME203#undef HAVE_FOO204#undef HAVE_BAR205```206207### 2.3.4. Библиотечные опции208209Также можно указать библиотеки, с которыми нужно компоновать расширение при сборке, и каталоги для поиска этих библиотек. Опция `libraries` задаёт список библиотек для компоновки, `library_dirs` – список каталогов для поиска библиотек на этапе компоновки, а `runtime_library_dirs` – список каталогов для поиска общих (динамически загружаемых) библиотек во время выполнения.210211Например, если требуется скомпоновать расширение с библиотеками, которые заведомо находятся в стандартном пути поиска библиотек в целевых системах,212213```python214Extension(...,215          libraries=['gdbm', 'readline'])216```217218Если нужно скомпоновать расширение с библиотеками в нестандартном расположении, необходимо указать это расположение в `library_dirs`:219220```python221Extension(...,222          library_dirs=['/usr/X11R6/lib'],223          libraries=['X11', 'Xt'])224```225226(Повторим: подобные непереносимые конструкции следует избегать, если планируется распространять свой код.)227228### 2.3.5. Прочие опции229230Существуют и другие опции, которые можно использовать для обработки особых случаев.231232Опция `optional` является логической; если она равна true, сбой сборки расширения не прервёт процесс сборки, а просто не приведёт к установке ошибочного расширения.233234Опция `extra_objects` задаёт список объектных файлов, передаваемых компоновщику. Эти файлы не должны иметь расширений, так как используется расширение по умолчанию для компилятора.235236`extra_compile_args` и `extra_link_args` можно использовать для указания дополнительных параметров командной строки для компилятора и компоновщика соответственно.237238`export_symbols` применим только в Windows. Он может содержать список символов (функций или переменных), подлежащих экспорту. Эта опция не нужна при сборке скомпилированных расширений: Distutils автоматически добавит `initmodule` в список экспортируемых символов.239240Опция `depends` задаёт список файлов, от которых зависит расширение (например, заголовочные файлы). Команда сборки вызовет компилятор для перестроения расширения, если какой-либо из этих файлов был изменён после предыдущей сборки.241242## 2.4. Взаимосвязи между дистрибутивами и пакетами243244Дистрибутив может относиться к пакетам тремя определёнными способами:2452461. Он может требовать пакеты или модули.2472. Он может предоставлять пакеты или модули.2483. Он может заменять (делать устаревшими) пакеты или модули.249250Эти взаимосвязи можно задать с помощью именованных аргументов функции [`distutils.core.setup()`](https://python-all.ru/3.10/distutils/apiref.html#distutils.core.setup).251252Зависимости от других модулей и пакетов Python можно указать, передав именованный аргумент *requires* функции `setup()`. Значение должно быть списком строк. Каждая строка задаёт необходимый пакет и, опционально, какие версии достаточны.253254Чтобы указать, что требуется любая версия модуля или пакета, строка должна состоять только из имени модуля или пакета. Примеры: `'mymodule'` и `'xml.parsers.expat'`.255256Если требуются конкретные версии, можно указать последовательность квалификаторов в скобках. Каждый квалификатор может состоять из оператора сравнения и номера версии. Допустимые операторы сравнения:257258```python259<    >    ==260<=   >=   !=261```262263Их можно комбинировать, используя несколько квалификаторов, разделённых запятыми (и необязательными пробелами). В этом случае все квалификаторы должны совпадать; используется логическое И для объединения результатов.264265Рассмотрим несколько примеров:266267| Выражение Requires | Пояснение |268| --- | --- |269| `==1.0` | Совместима только версия `1.0` |270| `>1.0, !=1.5.1, <2.0` | Любая версия после `1.0` и до `2.0` совместима, за исключением `1.5.1` |271272Теперь, когда мы умеем указывать зависимости, нам также нужно уметь указывать, что мы предоставляем и что могут требовать другие дистрибутивы. Это делается с помощью именованного аргумента *provides* функции `setup()`. Значение этого аргумента – список строк, каждая из которых указывает имя модуля или пакета и, опционально, версию. Если версия не указана, считается, что она совпадает с версией дистрибутива.273274Несколько примеров:275276| Выражение Provides | Пояснение |277| --- | --- |278| `mypkg` | Предоставить `mypkg`, используя версию дистрибутива |279| `mypkg (1.1)` | Предоставить `mypkg` версии 1.1, независимо от версии дистрибутива |280281Пакет может объявлять, что он заменяет (делает устаревшими) другие пакеты, с помощью именованного аргумента *obsoletes*. Его значение аналогично значению аргумента *requires*: список строк, задающих спецификаторы модуля или пакета. Каждый спецификатор состоит из имени модуля или пакета, за которым необязательно следуют один или несколько квалификаторов версии. Версионные квалификаторы указываются в скобках после имени модуля или пакета.282283Версии, указанные квалификаторами, считаются заменяемыми (устаревшими) данным дистрибутивом. Если квалификаторы не указаны, считаются устаревшими все версии указанного модуля или пакета.284285## 2.5. Установка скриптов286287До сих пор мы имели дело с чистыми и нечистыми модулями Python, которые обычно не запускаются сами по себе, а импортируются скриптами.288289Скрипты – это файлы, содержащие исходный код Python, предназначенные для запуска из командной строки. Скрипты не требуют от Distutils каких-либо сложных действий. Единственная умная особенность: если первая строка скрипта начинается с `#!` и содержит слово «python», Distutils изменит первую строку так, чтобы она указывала на текущий интерпретатор. По умолчанию она заменяется на путь к текущему интерпретатору. Опция `--executable` (или `-e`) позволяет явно переопределить путь к интерпретатору.290291Опция `scripts` – это просто список файлов, которые обрабатываются таким образом. Из скрипта установки PyXML:292293```python294setup(...,295      scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']296      )297```298299Изменено в версии 3.1: Все скрипты также будут добавлены в файл `MANIFEST`, если не предоставлен шаблон. См. [Указание файлов для распространения](https://python-all.ru/3.10/distutils/sourcedist.html#manifest).300301## 2.6. Установка данных пакета302303Часто в пакет нужно установить дополнительные файлы. Эти файлы – обычно данные, тесно связанные с реализацией пакета, или текстовые файлы с документацией, которая может быть полезна программистам, использующим пакет. Такие файлы называются *данными пакета*.304305Данные пакета можно добавить в пакеты с помощью ключевого аргумента `package_data` функции `setup()`. Значением должно быть отображение имени пакета на список относительных путей, которые нужно скопировать в пакет. Пути интерпретируются относительно каталога, содержащего пакет (при необходимости используется информация из отображения `package_dir`); то есть ожидается, что файлы являются частью пакета в исходных каталогах. Они также могут содержать glob-шаблоны.306307Имена путей могут содержать части каталогов; все необходимые каталоги будут созданы при установке.308309Например, если пакет должен содержать подкаталог с несколькими файлами данных, файлы можно расположить в дереве исходников следующим образом:310311```python312setup.py313src/314    mypkg/315        __init__.py316        module.py317        data/318            tables.dat319            spoons.dat320            forks.dat321```322323Соответствующий вызов `setup()` может быть таким:324325```python326setup(...,327      packages=['mypkg'],328      package_dir={'mypkg': 'src/mypkg'},329      package_data={'mypkg': ['data/*.dat']},330      )331```332333Изменено в версии 3.1: Все файлы, соответствующие `package_data`, будут добавлены в файл `MANIFEST`, если не предоставлен шаблон. См. [Указание файлов для распространения](https://python-all.ru/3.10/distutils/sourcedist.html#manifest).334335## 2.7. Установка дополнительных файлов336337Опция `data_files` может использоваться для указания дополнительных файлов, необходимых для распространяемого модуля: файлов конфигурации, каталогов сообщений, файлов данных, всего, что не подходит под предыдущие категории.338339`data_files` задаёт последовательность пар (*каталог*, *файлы*) следующим образом:340341```python342setup(...,343      data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),344                  ('config', ['cfg/data.cfg'])],345     )346```347348Каждая пара (*каталог*, *файлы*) в последовательности указывает каталог установки и файлы, которые следует туда установить.349350Каждое имя файла в *files* интерпретируется относительно скрипта `setup.py` в корне исходного дистрибутива пакета. Обратите внимание: можно указать каталог, куда будут установлены файлы данных, но нельзя переименовать сами файлы данных.351352Параметр *directory* должен быть относительным путём. Он интерпретируется относительно префикса установки (`sys.prefix` Python для системных установок; `site.USER_BASE` для пользовательских установок). Distutils позволяет *directory* быть абсолютным путём установки, но это не рекомендуется, так как несовместимо с форматом упаковки wheel. Информация о каталогах из *files* не используется для определения конечного расположения устанавливаемого файла; используется только имя файла.353354Можно указать опцию `data_files` как простую последовательность файлов без указания целевого каталога, но это не рекомендуется, и команда **install** выведет предупреждение. Чтобы установить файлы данных непосредственно в целевой каталог, в качестве каталога нужно задать пустую строку.355356Изменено в версии 3.1: Все файлы, соответствующие `data_files`, будут добавлены в файл `MANIFEST`, если не предоставлен шаблон. См. [Указание файлов для распространения](https://python-all.ru/3.10/distutils/sourcedist.html#manifest).357358## 2.8. Дополнительные метаданные359360Скрипт setup может включать дополнительные метаданные помимо имени и версии. Эта информация включает:361362| Метаданные | Описание | Значение | Примечания |363| --- | --- | --- | --- |364| `name` | имя пакета | короткая строка | (1) |365| `version` | версия этого релиза | короткая строка | (1)(2) |366| `author` | имя автора пакета | короткая строка | (3) |367| `author_email` | адрес электронной почты автора пакета | адрес электронной почты | (3) |368| `maintainer` | имя сопровождающего пакета | короткая строка | (3) |369| `maintainer_email` | адрес электронной почты сопровождающего пакет | адрес электронной почты | (3) |370| `url` | домашняя страница пакета | URL | (1) |371| `description` | краткое описание пакета | короткая строка |  |372| `long_description` | подробное описание пакета | длинная строка | (4) |373| `download_url` | расположение, откуда можно загрузить пакет | URL |  |374| `classifiers` | список классификаторов | список строк | (6)(7) |375| `platforms` | список платформ | список строк | (6)(8) |376| `keywords` | список ключевых слов | список строк | (6)(8) |377| `license` | лицензия для пакета | короткая строка | (5) |378379Примечания:3803811. Эти поля обязательны.3822. Рекомендуется, чтобы версии имели формат *major.minor\[.patch\[.sub\]\]*.3833. Должен быть указан либо автор, либо сопровождающий. Если указан сопровождающий, distutils указывает его как автора в `PKG-INFO`.3844. Поле `long_description` используется PyPI при публикации пакета для построения его страницы проекта.3855. Поле `license` – это текст, указывающий лицензию, покрывающую пакет, если лицензия не выбрана из классификаторов Trove «License». См. поле `Classifier`. Обратите внимание, что существует опция распространения `licence`, которая устарела, но всё ещё является псевдонимом для `license`.3866. Это поле должно быть списком.3877. Допустимые классификаторы перечислены на [PyPI](https://python-all.ru/3.10/distutils/setupscript.html).3888. Для сохранения обратной совместимости это поле также принимает строку. Если передана строка, разделённая запятыми, `'foo, bar'`, она будет преобразована в `['foo', 'bar']`, в противном случае будет преобразована в список из одной строки.389390**«короткая строка»**391392Одна строка текста, не более 200 символов.393394**«длинная строка»**395396Несколько строк обычного текста в формате reStructuredText (см. [http://docutils.sourceforge.net/](https://python-all.ru/3.10/distutils/setupscript.html)).397398**«список строк»**399400См. ниже.401402Кодирование информации о версии – само по себе искусство. Пакеты Python обычно придерживаются формата версии *major.minor\[.patch\]\[sub\]*. Основной номер (major) равен 0 для начальных экспериментальных выпусков ПО. Он увеличивается для выпусков, представляющих собой важные вехи в пакете. Дополнительный номер (minor) увеличивается, когда в пакет добавляются важные новые функции. Номер патча увеличивается при выпусках с исправлением ошибок. Иногда дополнительная информация о версии в конце используется для обозначения подвыпусков. Это «a1,a2,…,aN» (для альфа-версий, где функциональность и API могут меняться), «b1,b2,…,bN» (для бета-версий, которые только исправляют ошибки) и «pr1,pr2,…,prN» (для финального тестирования перед релизом). Некоторые примеры:403404**0.1.0**405406первый экспериментальный выпуск пакета407408**1.0.1a2**409410второй альфа-выпуск первой патч-версии 1.0411412`classifiers` должен быть указан в виде списка:413414```python415setup(...,416      classifiers=[417          'Development Status :: 4 - Beta',418          'Environment :: Console',419          'Environment :: Web Environment',420          'Intended Audience :: End Users/Desktop',421          'Intended Audience :: Developers',422          'Intended Audience :: System Administrators',423          'License :: OSI Approved :: Python Software Foundation License',424          'Operating System :: MacOS :: MacOS X',425          'Operating System :: Microsoft :: Windows',426          'Operating System :: POSIX',427          'Programming Language :: Python',428          'Topic :: Communications :: Email',429          'Topic :: Office/Business',430          'Topic :: Software Development :: Bug Tracking',431          ],432      )433```434435Изменено в версии 3.7: [`setup`](https://python-all.ru/3.10/distutils/apiref.html#distutils.core.setup) теперь предупреждает, если поля `classifiers`, `keywords` или `platforms` не указаны в виде списка или строки.436437## 2.9. Отладка скрипта установки438439Иногда что-то идет не так, и скрипт установки делает не то, что хочет разработчик.440441Distutils перехватывает любые исключения при запуске скрипта установки и выводит простое сообщение об ошибке перед завершением скрипта. Причина такого поведения – не запутывать администраторов, которые мало знают о Python и пытаются установить пакет. Если они получат длинную трассировку из глубин Distutils, они могут подумать, что пакет или установка Python сломаны, потому что не прочитают все до конца и не увидят, что проблема в правах доступа.442443С другой стороны, это не помогает разработчику найти причину сбоя. Для этой цели переменная окружения `DISTUTILS_DEBUG` может быть установлена в любое значение, кроме пустой строки, и distutils теперь будет выводить подробную информацию о том, что он делает, выводить полную трассировку при возникновении исключения и выводить всю командную строку при сбое внешней программы (например, компилятора C).444