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