Примеры Distutils
Примечание
Данный документ сохраняется только до тех пор, пока документация setuptools по адресу https://setuptools.readthedocs.io/en/latest/setuptools.html не будет содержать всю необходимую информацию, в настоящее время представленную здесь.
В данном разделе представлены несколько основных примеров, которые помогут начать работу с distutils. Дополнительную информацию об использовании distutils можно найти в руководстве по distutils.
См. также
- Руководство по distutils
-
Коллекция рецептов, показывающих, как получить больший контроль над distutils.
6.1. Распространение чистого Python-модуля (по модулям)
Если вы только распределяете несколько модулей, особенно если они не находятся в конкретном пакете, вы можете указать их индивидуально, используя параметр py_modules в скрипте настройки.
В самом простом случае вам нужно будет позаботиться о двух файлах: скрипте настройки и единственном модуле, который вы распространяете, foo.py в этом примере:
<root>/
setup.py
foo.py
(Во всех диаграммах в этом разделе <root> будет ссылаться на корневой каталог распространения.) Минимальный скрипт настройки для описания этой ситуации будет:
from distutils.core import setup
setup(name='foo',
version='1.0',
py_modules=['foo'],
)
Обратите внимание, что имя распространения указывается независимо с помощью параметра name, и нет правила, гласящего, что оно должно совпадать с именем единственного модуля в распространении (хотя это, вероятно, хорошая соглашение). Однако имя распространения используется для генерации имен файлов, поэтому вы должны придерживаться букв, цифр, символов подчеркивания и дефисов.
Поскольку py_modules является списком, вы можете, конечно, указать несколько модулей, например, если вы распространяете модули foo и bar, ваша настройка может выглядеть так:
<root>/
setup.py
foo.py
bar.py
и скрипт настройки может быть
from distutils.core import setup
setup(name='foobar',
version='1.0',
py_modules=['foo', 'bar'],
)
Вы можете поместить исходные файлы модулей в другую директорию, но если у вас достаточно модулей для этого, скорее всего, проще указать модули по пакетам, чем перечислять их по отдельности.
6.2. Распространение чистого Python-пакета
Если вам нужно распространить более нескольких модулей, особенно если они находятся в нескольких пакетах, скорее всего, проще указать целые пакеты, а не отдельные модули. Это работает даже если ваши модули не находятся в пакете; вы можете просто сказать distutils обрабатывать модули из корневого пакета, и это работает так же, как и с любым другим пакетом (за исключением того, что вам не нужно иметь файл __init__.py).
Скрипт настройки из предыдущего примера также можно записать так
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, и та, которая требует наименьших усилий при описании в вашем скрипте настройки:
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
Или же вы можете поместить модули своего основного пакета прямо в корневой каталог распространения:
<root>/
setup.py
__init__.py
foo.py
bar.py
В этом случае ваш скрипт настроек будет выглядеть так
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
соответствующий скрипт настроек будет выглядеть так
from distutils.core import setup
setup(name='foobar',
version='1.0',
packages=['foobar', 'foobar.subfoo'],
)
6.3. Модуль единственного расширения
Модули расширений указываются с помощью параметра ext_modules. package_dir не влияет на расположение исходных файлов расширения; он влияет только на исходные файлы чистого Python. Самый простой случай, один модуль расширения в одном исходном файле C:
<root>/
setup.py
foo.c
Если расширение foo принадлежит корневому пакету, скрипт настроек для этого может быть
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'])],
)
6.4. Проверка пакета
Команда 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.
6.5. Чтение метаданных
Функция distutils.core.setup() предоставляет интерфейс командной строки, который позволяет вам получить доступ к полям метаданных проекта с помощью скрипта setup.py данного проекта:
$ python setup.py --name distribute
Этот вызов считывает метаданные name, выполняя функцию distutils.core.setup(). Однако, когда с помощью Distutils создаётся исходное или двоичное распределение, поля метаданных записываются в статический файл, называемый PKG-INFO. При установке проекта, основанного на Distutils, в Python, файл PKG-INFO копируется вместе с модулями и пакетами распространения в NAME-VERSION-pyX.X.egg-info, где NAME - имя проекта, VERSION - его версия, определенная в метаданных, а pyX.X - основные и второстепенные версии Python, как 2.7 или 3.2.
Вы можете прочитать этот статический файл, используя класс distutils.dist.DistributionMetadata и его метод read_pkg_file().
>>> from distutils.dist import DistributionMetadata
>>> metadata = DistributionMetadata()
>>> metadata.read_pkg_file(open('distribute-0.6.8-py2.7.egg-info'))
>>> metadata.name
'distribute'
>>> metadata.version
'0.6.8'
>>> metadata.description
'Easily download, build, install, upgrade, and uninstall Python packages'
Обратите внимание, что класс также может быть инициализирован путем передачи пути к файлу метаданных для загрузки его значений:
>>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info' >>> DistributionMetadata(pkg_info_path).name 'distribute'
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/distutils/examples.html