Примеры Distutils
Примечание
Этот документ сохраняется только до тех пор, пока документация setuptools по адресу https://setuptools.readthedocs.io/en/latest/setuptools.html самостоятельно не покроет всю актуальную информацию, включённую сюда.
В этой главе представлены несколько основных примеров, которые помогут начать работу с distutils. Дополнительную информацию об использовании distutils можно найти в руководстве по distutils.
См. также
- Руководство по distutils
-
Сборник рецептов, демонстрирующих, как получить больший контроль над distutils.
6.1. Распространение чистого Python (по модулям)
Если вы распределяете всего пару модулей, особенно если они не находятся в конкретном пакете, вы можете указать их индивидуально, используя опцию 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'],
)
Вы можете поместить исходные файлы модулей в другой каталог, но если у вас достаточно модулей для этого, то, вероятно, проще указать модули по пакетам, а не перечислять их индивидуально.
6.2. Распространение чистого Python (по пакетам)
Если вам нужно распространить более пары модулей, особенно если они находятся в нескольких пакетах, вероятно, проще указать целые пакеты, а не отдельные модули. Это работает даже если ваши модули не находятся в пакете; вы можете просто сказать 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'],
)
6.3. Модуль с одним расширением
Модули с расширениями указываются с помощью опции 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'])],
)
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.11/distutils/examples.html