Примеры использования 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
(Во всех диаграммах в этом разделе <корень> будет ссылаться на корневой каталог распространения.) Минимальный скрипт настройки для описания этой ситуации будет:
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
соответствующий скрипт настройки будет
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
в этом случае ваш скрипт настройки будет
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) should 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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/distutils/examples.html