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 работает с сторонними пакетами распределения, установленных в каталог Python site-packages с помощью таких инструментов, как 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 не принимал параметров и всегда возвращал словарь точек входа, индексированных по группам. С importlib_metadata 5.0 и Python 3.12, entry_points всегда возвращает объект EntryPoints. См. backports.entry_points_selectable для вариантов совместимости.
Данные о распространении
Каждый пакет распространения включает некоторые метаданные, которые можно извлечь с помощью функции 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 теперь включен в метаданные, представленные в нагрузке. Символы перевода строки удалены.
Добавлен атрибут 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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/importlib.metadata.html