Spec-Zone.ru › Python 3.11

importlib.metadata – Доступ к метаданным пакетов

Новое в версии 3.8.

Изменено в версии 3.10: importlib.metadata больше не является предварительным.

Исходный код: Lib/importlib/metadata/__init__.py

importlib.metadata — это библиотека, предоставляющая доступ к метаданным установленного пакета дистрибуции, например, к его точкам входа или его именам верхнего уровня (пакеты импорта, модули, если таковые имеются). Эта библиотека, частично построенная на системе импорта Python, предназначена для замены аналогичных функций в API точек входа и API метаданных pkg_resources. Вместе с importlib.resources этот пакет может устранить необходимость использования более старого и менее эффективного пакета pkg_resources.

importlib.metadata работает с сторонними пакетами дистрибуции, установленными в каталог site-packages Python через инструменты, такие как pip. В частности, он работает с дистрибутивами, содержащими обнаруживаемые dist-info или egg-info каталоги, и метаданными, определенными в спецификациях основных метаданных.

Важно

Эти метаданные не обязательно эквивалентны или соответствуют 1:1 именам пакетов импорта верхнего уровня, которые можно импортировать внутри кода Python. Один пакет дистрибуции может содержать несколько пакетов импорта (и отдельные модули), а один пакет импорта верхнего уровня может соответствовать нескольким пакетам дистрибуции, если это пакет пространства имен. Вы можете использовать package_distributions() для получения соответствия между ними.

По умолчанию, метаданные дистрибутива могут храниться в файловой системе или в zip-архивах в sys.path. С помощью механизма расширения метаданные могут храниться практически где угодно.

См. также

https://importlib-metadata.readthedocs.io/

Документация для importlib_metadata, которая предоставляет бэкпорт importlib.metadata. Она включает ссылку на справочник API классов и функций этого модуля, а также руководство по миграции для существующих пользователей pkg_resources.

Обзор

Предположим, вам нужно получить строку версии для пакета дистрибуции, который вы установили с помощью pip. Мы начнём с создания виртуальной среды и установки чего-то в неё:

$ python -m venv example
$ source example/bin/activate
(example) $ python -m pip install wheel

Вы можете получить строку версии для wheel, выполнив следующее:

(example) $ python
>>> from importlib.metadata import version  
>>> version('wheel')  
'0.32.3'

Вы также можете получить коллекцию точек входа, выбираемых по свойствам точки входа (обычно «группа» или «имя»), таких как console_scripts, distutils.commands и другие. Каждая группа содержит коллекцию объектов EntryPoint.

Вы можете получить метаданные дистрибутива:

>>> list(metadata('wheel'))  
['Metadata-Version', 'Name', 'Version', 'Summary', 'Home-page', 'Author', 'Author-email', 'Maintainer', 'Maintainer-email', 'License', 'Project-URL', 'Project-URL', 'Project-URL', 'Keywords', 'Platform', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Requires-Python', 'Provides-Extra', 'Requires-Dist', 'Requires-Dist']

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

Функциональный API

Этот пакет предоставляет следующую функциональность через свой публичный API.

Точки входа

Функция entry_points() возвращает коллекцию точек входа. Точки входа представлены экземплярами EntryPoint; каждый экземпляр EntryPoint имеет атрибуты .name, .group и .value, а также метод .load() для разрешения значения. Также есть атрибуты .module, .attr и .extras для получения компонентов атрибута .value.

Запрос всех точек входа:

>>> eps = entry_points()  

Функция entry_points() возвращает объект EntryPoints, коллекцию всех объектов EntryPoint с атрибутами names и groups для удобства:

>>> sorted(eps.groups)  
['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation']

EntryPoints имеет метод select для выбора точек входа, соответствующих определённым свойствам. Выберите точки входа в группе console_scripts:

>>> scripts = eps.select(group='console_scripts')  

Аналогично, поскольку entry_points передаёт ключевые аргументы для выбора:

>>> scripts = entry_points(group='console_scripts')  

Выберите определённый скрипт с именем “wheel” (найденный в проекте wheel):

>>> 'wheel' in scripts.names  
True
>>> wheel = scripts['wheel']  

Аналогично, запросите эту точку входа во время выбора:

>>> (wheel,) = entry_points(group='console_scripts', name='wheel')  
>>> (wheel,) = entry_points().select(group='console_scripts', name='wheel')  

Проверьте разрешённую точку входа:

>>> wheel  
EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')
>>> wheel.module  
'wheel.cli'
>>> wheel.attr  
'main'
>>> wheel.extras  
[]
>>> main = wheel.load()  
>>> main  
<function main at 0x103528488>

group и name — произвольные значения, определённые автором пакета, и обычно клиент захочет разрешить все точки входа для конкретной группы. Для получения дополнительной информации о точках входа, их определении и использовании, обратитесь к документации setuptools.

Примечание по совместимости

Точки входа «selectable» были введены в importlib_metadata 3.6 и Python 3.10. До этих изменений entry_points не принимал параметров и всегда возвращал словарь точек входа, ключами которого были группы. Для совместимости, если параметрам не передаются параметры, возвращается объект SelectableGroups, реализующий интерфейс dict. В будущем вызов entry_points без параметров будет возвращать объект EntryPoints. Пользователи должны полагаться на интерфейс выбора для извлечения точек входа по группам.

Данные о дистрибутиве

Каждый пакет дистрибутива включает некоторые метаданные, которые можно извлечь с помощью функции metadata():

>>> wheel_metadata = metadata('wheel')  

Ключи возвращаемой структуры данных, PackageMetadata, называют метаданные ключевые слова, а значения возвращаются необработанными из метаданных дистрибутива:

>>> wheel_metadata['Requires-Python']  
'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'

PackageMetadata также предоставляет атрибут json, который возвращает все метаданные в формате, совместимом с JSON, в соответствии с PEP 566:

>>> wheel_metadata.json['requires_python']
'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'

Примечание

Фактический тип объекта, возвращаемого metadata(), является деталью реализации и должен быть доступен только через интерфейс, описанный в протоколе PackageMetadata.

Изменено в версии 3.10: Description теперь включён в метаданные при представлении через запрос. Символы перевода строки удалены.

Добавлена в версии 3.10: Атрибут json был добавлен.

Версии дистрибутива

Функция version() — самый быстрый способ получить номер версии пакета дистрибутива в виде строки:

>>> version('wheel')  
'0.32.3'

Файлы дистрибутива

Вы также можете получить полный набор файлов, содержащихся в дистрибутиве. Функция files() принимает имя пакета дистрибутива и возвращает все файлы, установленные этим дистрибутивом. Каждый возвращаемый объект файла является PackagePath, объектом, производным от pathlib.PurePath, с дополнительными свойствами dist, size и hash, как указано в метаданных. Например:

>>> util = [p for p in files('wheel') if 'util.py' in str(p)][0]  
>>> util  
PackagePath('wheel/util.py')
>>> util.size  
859
>>> util.dist  
<importlib.metadata._hooks.PathDistribution object at 0x101e0cef0>
>>> util.hash  
<FileHash mode: sha256 value: bYkw5oMccfazVCoYQwKkkemoVyMAFoR34mmKBx8R1NI>

После получения файла вы также можете прочитать его содержимое:

>>> print(util.read_text())  
import base64
import sys
...
def as_bytes(s):
    if isinstance(s, text_type):
        return s.encode('utf-8')
    return s

Вы также можете использовать метод locate для получения абсолютного пути к файлу:

>>> util.locate()  
PosixPath('/home/gustav/example/lib/site-packages/wheel/util.py')

В случае отсутствия файла метаданных, перечисляющего файлы (RECORD или SOURCES.txt), files() вернёт None. Вызывающая сторона может захотеть обернуть вызовы files() в always_iterable или каким-либо другим способом защитить от этого условия, если известно, что целевой дистрибутив не имеет необходимых метаданных.

Требования к дистрибутиву

Чтобы получить полный набор требований к пакету дистрибутива, используйте функцию requires():

>>> requires('wheel')  
["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]

Сопоставление импорта с пакетами дистрибутива

Удобный метод для разрешения имени пакета дистрибутива (или имён в случае пакетного пространства имён), которые предоставляют каждый импортируемый верхнеуровневый модуль Python или пакет импорта:

>>> packages_distributions()
{'importlib_metadata': ['importlib-metadata'], 'yaml': ['PyYAML'], 'jaraco': ['jaraco.classes', 'jaraco.functools'], ...}

Добавлена в версии 3.10.

Дистрибутивы

Хотя вышеприведённый API является наиболее распространённым и удобным вариантом использования, вы можете получить всю эту информацию из класса Distribution. Distribution — это абстрактный объект, представляющий метаданные для Python пакета дистрибутива. Вы можете получить экземпляр Distribution:

>>> from importlib.metadata import distribution  
>>> dist = distribution('wheel')  

Таким образом, альтернативный способ получения номера версии — через экземпляр Distribution:

>>> dist.version  
'0.32.3'

Существует множество дополнительных метаданных, доступных в экземпляре Distribution:

>>> dist.metadata['Requires-Python']  
'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
>>> dist.metadata['License']  
'MIT'

Полный набор доступных метаданных здесь не описан. Для получения дополнительных сведений см. спецификации основных метаданных.

Обнаружение дистрибутивов

По умолчанию этот пакет предоставляет встроенную поддержку обнаружения метаданных для файлов и zip-архивов пакетов дистрибутива. Этот поиск метаданных по умолчанию использует sys.path, но несколько отличается в том, как он интерпретирует эти значения по сравнению с другими механизмами импорта. В частности:

  • importlib.metadata не учитывает объекты bytes в sys.path.
  • importlib.metadata случайно учитывает объекты pathlib.Path в sys.path, хотя такие значения будут проигнорированы при импорте.

Расширение алгоритма поиска

Поскольку метаданные пакетов дистрибутива недоступны через поиск в sys.path или непосредственно через загрузчики пакетов, метаданные дистрибутива обнаруживаются с помощью поисковиков системы импорта. Для поиска метаданных пакета дистрибутива importlib.metadata просматривает список поисковиков метапути в sys.meta_path.

По умолчанию importlib.metadata устанавливает поисковик для пакетов дистрибутива, найденных в файловой системе. Этот поисковик фактически не находит сами дистрибутивы, но может найти их метаданные.

Абстрактный класс importlib.abc.MetaPathFinder определяет ожидаемый интерфейс для поисковиков в системе импорта Python. importlib.metadata расширяет этот протокол, ища необязательный вызов find_distributions в поисковиках из sys.meta_path и представляет этот расширенный интерфейс как абстрактный базовый класс DistributionFinder, который определяет этот абстрактный метод:

@abc.abstractmethod
def find_distributions(context=DistributionFinder.Context()):
    """Return an iterable of all Distribution instances capable of
    loading the metadata for packages for the indicated ``context``.
    """

Объект DistributionFinder.Context предоставляет свойства .path и .name, указывающие на путь для поиска и имя для сопоставления, и может предоставлять другой релевантный контекст.

На практике это означает, что для поддержки поиска метаданных пакетов дистрибутива в местах, отличных от файловой системы, необходимо унаследовать от Distribution и реализовать абстрактные методы. Затем из пользовательского поисковика необходимо возвращать экземпляры этого производного класса Distribution в методе find_distributions().

© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/importlib.metadata.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API