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

7. ПримерыExamples

Эта глава содержит несколько базовых примеров, которые помогут начать работу с distutils. Дополнительную информацию об использовании distutils можно найти в Distutils Cookbook.

См. также

Кулинарная книга Distutils
Сборник рецептов, показывающих, как получить больше контроля над distutils.

7.1. Дистрибутив чистого Python (по модулям)Pure Python distribution (by module)

Если распространяется всего несколько модулей, особенно если они не находятся в определённом пакете, их можно указать по отдельности с помощью опции py_modules в скрипте setup.

В простейшем случае понадобятся два файла: скрипт setup и единственный распространяемый модуль foo.py в этом примере:

<root>/
        setup.py
        foo.py

(На всех схемах в этом разделе <root> обозначает корневой каталог дистрибутива.) Минимальный скрипт setup для описания этой ситуации будет выглядеть так:

from distutils.core import setup
setup(name='foo',
      version='1.0',
      py_modules=['foo'],
      )

Обратите внимание, что имя дистрибутива указывается независимо с помощью опции name, и нет правила, которое бы гласило, что оно должно совпадать с именем единственного модуля в дистрибутиве (хотя это, вероятно, хорошее соглашение, которому стоит следовать). Однако имя дистрибутива используется для генерации имён файлов, поэтому следует использовать только буквы, цифры, символы подчёркивания и дефисы.

Поскольку py_modules является списком, можно, конечно, указать несколько модулей, например, если распространяются модули foo и bar, ваш скрипт setup может выглядеть так:

<root>/
        setup.py
        foo.py
        bar.py

а скрипт setup может быть таким:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      py_modules=['foo', 'bar'],
      )

Вы можете поместить исходные файлы модулей в другой каталог, но если у вас достаточно модулей для этого, вероятно, проще указывать модули по пакетам, а не перечислять их по отдельности.

7.2. Дистрибутив чистого Python (по пакетам)Pure Python distribution (by package)

Если нужно распространять более нескольких модулей, особенно если они находятся в нескольких пакетах, вероятно, проще указать целые пакеты, а не отдельные модули. Это работает даже если модули не находятся в пакете; можно просто указать Distutils обрабатывать модули из корневого пакета, и это работает так же, как с любым другим пакетом (за исключением того, что не нужно иметь файл __init__.py).

Скрипт setup из предыдущего примера можно также записать как

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      packages=[''],
      )

(Пустая строка обозначает корневой пакет.)

Если эти два файла перемещены в подкаталог, но остаются в корневом пакете, например:

<root>/
        setup.py
        src/      foo.py
                  bar.py

тогда вы по-прежнему указываете корневой пакет, но должны сообщить Distutils, где находятся исходные файлы в корневом пакете:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      package_dir={'': 'src'},
      packages=[''],
      )

Однако чаще требуется распространять несколько модулей в одном пакете (или в подпакетах). Например, если модули foo и bar принадлежат пакету foobar, один из способов организовать дерево исходных кодов – это

<root>/
        setup.py
        foobar/
                 __init__.py
                 foo.py
                 bar.py

Фактически это стандартная структура, ожидаемая Distutils, и та, что требует наименьших усилий для описания в вашем скрипте setup:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      packages=['foobar'],
      )

Если требуется поместить модули в каталоги, имена которых не соответствуют их пакету, то необходимо снова использовать опцию package_dir. Например, если каталог src содержит модули пакета foobar:

<root>/
        setup.py
        src/
                 __init__.py
                 foo.py
                 bar.py

соответствующий скрипт setup будет таким:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      package_dir={'foobar': 'src'},
      packages=['foobar'],
      )

Или же можно поместить модули из главного пакета прямо в корневой каталог дистрибутива:

<root>/
        setup.py
        __init__.py
        foo.py
        bar.py

в этом случае скрипт setup будет таким:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      package_dir={'foobar': ''},
      packages=['foobar'],
      )

(Пустая строка также обозначает текущий каталог.)

Если имеются вложенные пакеты, они должны быть явно перечислены в packages, но любые записи в package_dir автоматически распространяются на вложенные пакеты. (Иными словами, Distutils не сканирует ваше дерево исходников, пытаясь выяснить, какие каталоги соответствуют пакетам Python, путём поиска файлов __init__.py.) Таким образом, если в стандартной структуре появляется вложенный пакет:

<root>/
        setup.py
        foobar/
                 __init__.py
                 foo.py
                 bar.py
                 subfoo/
                           __init__.py
                           blah.py

тогда соответствующий скрипт setup будет таким:

from distutils.core import setup
setup(name='foobar',
      version='1.0',
      packages=['foobar', 'foobar.subfoo'],
      )

(И снова пустая строка в package_dir обозначает текущий каталог.)

7.3. Одиночный модуль расширенияSingle extension module

Модули расширения указываются с помощью опции ext_modules. Опция package_dir не влияет на то, где находятся исходные файлы расширения; она влияет только на исходные файлы чистых модулей Python. Простейший случай – один модуль расширения в одном файле исходного кода на C – выглядит так:

<root>/
        setup.py
        foo.c

Если расширение foo принадлежит корневому пакету, скрипт setup для этого может быть таким:

from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[Extension('foo', ['foo.c'])],
      )

Если расширение на самом деле принадлежит пакету, скажем foopkg, то

При той же самой структуре дерева исходных кодов это расширение можно поместить в пакет foopkg, просто изменив имя расширения:

from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[Extension('foopkg.foo', ['foo.c'])],
      )

7.4. Проверка пакетаChecking a package

Команда check позволяет проверить, соответствует ли мета-информация пакета минимальным требованиям для сборки дистрибутива.

Чтобы запустить её, достаточно вызвать её с помощью скрипта setup.py. Если чего-то не хватает, check выведет предупреждение.

Рассмотрим пример с простым скриптом:

from distutils.core import setup

setup(name='foobar')

При запуске команды check будут выведены некоторые предупреждения:

$ python setup.py check
running check
warning: check: missing required meta-data: version, url
warning: check: missing meta-data: either (author and author_email) or
         (maintainer and maintainer_email) must be supplied

Если используется синтаксис reStructuredText в поле long_description и установлен docutils, можно проверить корректность синтаксиса с помощью команды check, используя параметр restructuredtext.

Например, если скрипт setup.py изменён следующим образом:

from distutils.core import setup

desc = """\
My description
=============

This is the description of the ``foobar`` package.
"""

setup(name='foobar', version='1', author='tarek',
    author_email='tarek@ziade.org',
    url='http://example.com', long_description=desc)

Если длинное описание содержит ошибки, check сможет обнаружить их, используя анализатор docutils:

$ python setup.py check --restructuredtext
running check
warning: check: Title underline too short. (line 2)
warning: check: Could not finish the parsing.