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

examples.md

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

1> **Источник:** https://python-all.ru/3.6/distutils/examples.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 7. Примеры89Эта глава содержит несколько базовых примеров, которые помогут начать работу с distutils. Дополнительную информацию об использовании distutils можно найти в Distutils Cookbook.1011> **См. также**12>13> **[Кулинарная книга Distutils](https://python-all.ru/3.6/distutils/examples.html)**14>15> Сборник рецептов, показывающих, как получить больше контроля над distutils.1617## 7.1. Распространение чистого Python (по модулям)1819Если вы распространяете всего несколько модулей, особенно если они не находятся в определённом пакете, вы можете указать их по отдельности с помощью параметра `py_modules` в скрипте setup.2021В простейшем случае вам понадобится всего два файла: скрипт setup и единственный модуль, который вы распространяете, `foo.py` в этом примере:2223```python24<root>/25        setup.py26        foo.py27```2829(На всех схемах в этом разделе *\<root\>* обозначает корневой каталог дистрибутива.) Минимальный скрипт setup для описания этой ситуации будет выглядеть так:3031```python32from distutils.core import setup33setup(name='foo',34      version='1.0',35      py_modules=['foo'],36      )37```3839Обратите внимание, что имя дистрибутива задаётся независимо с помощью параметра `name`, и нет правила, что оно должно совпадать с именем единственного модуля в дистрибутиве (хотя это, вероятно, хорошее соглашение). Однако имя дистрибутива используется для генерации имён файлов, поэтому следует использовать только буквы, цифры, символы подчёркивания и дефисы.4041Поскольку `py_modules` – это список, вы, конечно, можете указать несколько модулей, например, если вы распространяете модули `foo` и `bar`, ваш setup может выглядеть так:4243```python44<root>/45        setup.py46        foo.py47        bar.py48```4950а скрипт setup может быть таким:5152```python53from distutils.core import setup54setup(name='foobar',55      version='1.0',56      py_modules=['foo', 'bar'],57      )58```5960Вы можете поместить исходные файлы модулей в другой каталог, но если у вас достаточно модулей для этого, вероятно, проще указывать модули по пакетам, а не перечислять их по отдельности.6162## 7.2. Распространение чистого Python (по пакетам)6364Если вам нужно распространять больше пары модулей, особенно если они находятся в нескольких пакетах, вероятно, проще указывать целые пакеты, а не отдельные модули. Это работает даже если ваши модули не в пакете; вы можете просто указать Distutils обрабатывать модули из корневого пакета, и это будет работать так же, как с любым другим пакетом (за исключением того, что вам не нужен файл `__init__.py`).6566Скрипт setup из предыдущего примера можно также записать как6768```python69from distutils.core import setup70setup(name='foobar',71      version='1.0',72      packages=[''],73      )74```7576(Пустая строка обозначает корневой пакет.)7778Если эти два файла перемещены в подкаталог, но остаются в корневом пакете, например:7980```python81<root>/82        setup.py83        src/      foo.py84                  bar.py85```8687тогда вы по-прежнему указываете корневой пакет, но должны сообщить Distutils, где находятся исходные файлы в корневом пакете:8889```python90from distutils.core import setup91setup(name='foobar',92      version='1.0',93      package_dir={'': 'src'},94      packages=[''],95      )96```9798Однако чаще требуется распространять несколько модулей в одном пакете (или в подпакетах). Например, если модули `foo` и `bar` принадлежат пакету `foobar`, один из способов организовать дерево исходников:99100```python101<root>/102        setup.py103        foobar/104                 __init__.py105                 foo.py106                 bar.py107```108109Фактически это стандартная структура, ожидаемая Distutils, и та, что требует наименьших усилий для описания в вашем скрипте setup:110111```python112from distutils.core import setup113setup(name='foobar',114      version='1.0',115      packages=['foobar'],116      )117```118119Если модули нужно поместить в каталоги, не названные по имени пакета, то следует снова использовать параметр `package_dir`. Например, если каталог `src` содержит модули пакета `foobar`:120121```python122<root>/123        setup.py124        src/125                 __init__.py126                 foo.py127                 bar.py128```129130соответствующий скрипт setup будет таким:131132```python133from distutils.core import setup134setup(name='foobar',135      version='1.0',136      package_dir={'foobar': 'src'},137      packages=['foobar'],138      )139```140141Или же можно поместить модули из главного пакета прямо в корневой каталог дистрибутива:142143```python144<root>/145        setup.py146        __init__.py147        foo.py148        bar.py149```150151в этом случае скрипт setup будет таким:152153```python154from distutils.core import setup155setup(name='foobar',156      version='1.0',157      package_dir={'foobar': ''},158      packages=['foobar'],159      )160```161162(Пустая строка также обозначает текущий каталог.)163164Если есть подпакеты, они должны быть явно перечислены в `packages`, но все записи в `package_dir` автоматически распространяются на подпакеты. (Другими словами, Distutils *не* сканирует дерево исходных файлов, пытаясь выяснить, какие каталоги соответствуют пакетам Python по наличию файлов `__init__.py`.) Таким образом, если в стандартной структуре появляется подпакет:165166```python167<root>/168        setup.py169        foobar/170                 __init__.py171                 foo.py172                 bar.py173                 subfoo/174                           __init__.py175                           blah.py176```177178тогда соответствующий скрипт setup будет таким:179180```python181from distutils.core import setup182setup(name='foobar',183      version='1.0',184      packages=['foobar', 'foobar.subfoo'],185      )186```187188## 7.3. Один модуль расширения189190Модули расширения задаются с помощью параметра `ext_modules`. `package_dir` не влияет на расположение исходных файлов расширения; он влияет только на исходные файлы чистых модулей Python. Самый простой случай – один модуль расширения в одном C-файле:191192```python193<root>/194        setup.py195        foo.c196```197198Если расширение `foo` принадлежит корневому пакету, скрипт setup для него может быть таким:199200```python201from distutils.core import setup202from distutils.extension import Extension203setup(name='foobar',204      version='1.0',205      ext_modules=[Extension('foo', ['foo.c'])],206      )207```208209Если расширение на самом деле принадлежит пакету, например `foopkg`, то:210211При той же структуре дерева исходных файлов это расширение можно поместить в пакет `foopkg`, просто изменив имя расширения:212213```python214from distutils.core import setup215from distutils.extension import Extension216setup(name='foobar',217      version='1.0',218      ext_modules=[Extension('foopkg.foo', ['foo.c'])],219      )220```221222## 7.4. Проверка пакета223224Команда `check` позволяет проверить, соответствуют ли метаданные пакета минимальным требованиям для сборки дистрибутива.225226Чтобы запустить её, достаточно вызвать её с помощью скрипта `setup.py`. Если чего-то не хватает, `check` выведет предупреждение.227228Рассмотрим пример с простым скриптом:229230```python231from distutils.core import setup232233setup(name='foobar')234```235236Запуск команды `check` выведет некоторые предупреждения:237238```console239$ python setup.py check240running check241warning: check: missing required meta-data: version, url242warning: check: missing meta-data: either (author and author_email) or243         (maintainer and maintainer_email) must be supplied244```245246Если в поле `long_description` используется синтаксис reStructuredText и установлены [docutils](https://python-all.ru/3.6/distutils/examples.html), можно проверить корректность синтаксиса командой `check` с параметром `restructuredtext`.247248Например, если скрипт `setup.py` изменить следующим образом:249250```python251from distutils.core import setup252253desc = """\254My description255==============256257This is the description of the ``foobar`` package.258"""259260setup(name='foobar', version='1', author='tarek',261    author_email='tarek@ziade.org',262    url='http://example.com', long_description=desc)263```264265Если длинное описание содержит ошибки, `check` сможет их обнаружить с помощью синтаксического анализатора `docutils`:266267```console268$ python setup.py check --restructuredtext269running check270warning: check: Title underline too short. (line 2)271warning: check: Could not finish the parsing.272```273274## 7.5. Чтение метаданных275276Функция [`distutils.core.setup()`](https://python-all.ru/3.6/distutils/apiref.html#distutils.core.setup) предоставляет интерфейс командной строки, позволяющий запрашивать поля метаданных проекта через скрипт `setup.py` этого проекта:277278```console279$ python setup.py --name280distribute281```282283Этот вызов читает метаданные `name`, запуская функцию [`distutils.core.setup()`](https://python-all.ru/3.6/distutils/apiref.html#distutils.core.setup). Однако, когда исходный или бинарный дистрибутив создаётся с помощью Distutils, поля метаданных записываются в статический файл с именем `PKG-INFO`. Когда проект на основе Distutils устанавливается в Python, файл `PKG-INFO` копируется вместе с модулями и пакетами дистрибутива в каталог `NAME-VERSION-pyX.X.egg-info`, где `NAME` – имя проекта, `VERSION` – его версия, определённая в метаданных, а `pyX.X` – major и minor версия Python, например `2.7` или `3.2`.284285Этот статический файл можно прочитать с помощью класса `distutils.dist.DistributionMetadata` и его метода `read_pkg_file()`:286287```python288>>> from distutils.dist import DistributionMetadata289>>> metadata = DistributionMetadata()290>>> metadata.read_pkg_file(open('distribute-0.6.8-py2.7.egg-info'))291>>> metadata.name292'distribute'293>>> metadata.version294'0.6.8'295>>> metadata.description296'Easily download, build, install, upgrade, and uninstall Python packages'297```298299Обратите внимание, что класс также можно инстанцировать с путём к файлу метаданных, чтобы загрузить его значения:300301```python302>>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info'303>>> DistributionMetadata(pkg_info_path).name304'distribute'305```306