importlib.metadata.md
1> **Источник:** https://python-all.ru/3.11/library/importlib.metadata.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `importlib.metadata` – Доступ к метаданным пакета89Новое в версии 3.8.1011Изменено в версии 3.10: `importlib.metadata` больше не является предварительным.1213**Исходный код:** [Lib/importlib/metadata/\_\_init\_\_.py](https://python-all.ru/src/3.11/Lib/importlib/metadata/__init__.py)1415`importlib.metadata` – библиотека, предоставляющая доступ к метаданным [установленного дистрибутивного пакета (Distribution Package)](https://python-all.ru/3.11/library/importlib.metadata.html), например, к его точкам входа (entry points) или именам верхнего уровня ([импортируемые пакеты (Import Package)](https://python-all.ru/3.11/library/importlib.metadata.html), модули, если они есть). Основанная на системе импорта Python, эта библиотека призвана заменить аналогичную функциональность из [API точек входа](https://python-all.ru/3.11/library/importlib.metadata.html) и [API метаданных](https://python-all.ru/3.11/library/importlib.metadata.html) из `pkg_resources`. Вместе с [`importlib.resources`](https://python-all.ru/3.11/library/importlib.resources.html#module-importlib.resources) этот пакет позволяет отказаться от использования более старого и менее эффективного пакета `pkg_resources`.1617`importlib.metadata` работает со сторонними *дистрибутивными пакетами*, установленными в каталог `site-packages` Python с помощью таких инструментов, как [pip](https://python-all.ru/3.11/library/importlib.metadata.html). В частности, он работает с дистрибутивами, имеющими обнаруживаемые каталоги `dist-info` или `egg-info`, и метаданными, определёнными [спецификациями основных метаданных](https://python-all.ru/3.11/library/importlib.metadata.html).1819> **Важно**20>21> Они *не обязательно* эквивалентны или соответствуют 1:1 именам верхнего уровня *импортируемых пакетов*, которые можно импортировать в коде Python. Один *дистрибутивный пакет* может содержать несколько *импортируемых пакетов* (и отдельных модулей), а один *импортируемый пакет* верхнего уровня может соответствовать нескольким *дистрибутивным пакетам*, если это пакет пространства имен. Для получения соответствия между ними можно использовать [package\_distributions()](https://python-all.ru/3.11/library/importlib.metadata.html#package-distributions).2223По умолчанию метаданные дистрибутива могут располагаться в файловой системе или в zip-архивах на [`sys.path`](https://python-all.ru/3.11/library/sys.html#sys.path). Благодаря механизму расширений метаданные могут находиться практически где угодно.2425> **См. также**26>27> **[https://importlib-metadata.readthedocs.io/](https://python-all.ru/3.11/library/importlib.metadata.html)**28>29> Документация для `importlib_metadata`, который предоставляет обратный порт `importlib.metadata`. Она включает [справочник API](https://python-all.ru/3.11/library/importlib.metadata.html) для классов и функций этого модуля, а также [руководство по миграции](https://python-all.ru/3.11/library/importlib.metadata.html) для существующих пользователей `pkg_resources`.3031## Обзор3233Допустим, нужно получить строку версии для [дистрибутивного пакета](https://python-all.ru/3.11/library/importlib.metadata.html), установленного с помощью `pip`. Начнём с создания виртуального окружения и установки чего-нибудь в него:3435```console36$ python -m venv example37$ source example/bin/activate38(example) $ python -m pip install wheel39```4041Вы можете получить строку версии для `wheel`, выполнив следующее:4243```pycon44(example) $ python45>>> from importlib.metadata import version 46>>> version('wheel') 47'0.32.3'48```4950Также можно получить набор точек входа, выбираемых по свойствам EntryPoint (обычно «group» или «name»), например, `console_scripts`, `distutils.commands` и другие. Каждая группа содержит набор объектов [EntryPoint](https://python-all.ru/3.11/library/importlib.metadata.html#entry-points).5152Вы можете получить [метаданные для дистрибутива](https://python-all.ru/3.11/library/importlib.metadata.html#metadata):5354```python55>>> list(metadata('wheel')) 56['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']57```5859Вы также можете получить [номер версии дистрибутива](https://python-all.ru/3.11/library/importlib.metadata.html#version), перечислить его [составные файлы](https://python-all.ru/3.11/library/importlib.metadata.html#files) и получить список [зависимостей дистрибутива](https://python-all.ru/3.11/library/importlib.metadata.html#requirements).6061## Функциональное API6263Этот пакет предоставляет следующие функции через свой публичный API.6465### Точки входа6667Функция `entry_points()` возвращает коллекцию точек входа. Точки входа представлены экземплярами `EntryPoint`; каждый `EntryPoint` имеет атрибуты `.name`, `.group` и `.value`, а также метод `.load()` для получения значения. Также есть атрибуты `.module`, `.attr` и `.extras` для получения компонентов атрибута `.value`.6869Запрос всех точек входа:7071```python72>>> eps = entry_points() 73```7475Функция `entry_points()` возвращает объект `EntryPoints`, коллекцию всех объектов `EntryPoint` с атрибутами `names` и `groups` для удобства:7677```python78>>> sorted(eps.groups) 79['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation']80```8182`EntryPoints` имеет метод `select` для выбора точек входа, соответствующих определённым свойствам. Выберите точки входа в группе `console_scripts`:8384```python85>>> scripts = eps.select(group='console_scripts') 86```8788Аналогично, поскольку `entry_points` передаёт ключевые аргументы в select:8990```python91>>> scripts = entry_points(group='console_scripts') 92```9394Выбрать конкретный скрипт с именем «wheel» (находится в проекте wheel):9596```python97>>> 'wheel' in scripts.names 98True99>>> wheel = scripts['wheel'] 100```101102Аналогично, запросить эту точку входа во время выбора:103104```python105>>> (wheel,) = entry_points(group='console_scripts', name='wheel') 106>>> (wheel,) = entry_points().select(group='console_scripts', name='wheel') 107```108109Проверить разрешённую точку входа:110111```python112>>> wheel 113EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')114>>> wheel.module 115'wheel.cli'116>>> wheel.attr 117'main'118>>> wheel.extras 119[]120>>> main = wheel.load() 121>>> main 122<function main at 0x103528488>123```124125`group` и `name` – произвольные значения, определяемые автором пакета; обычно клиент хочет получить все точки входа для определённой группы. Подробнее о точках входа, их определении и использовании читайте в [документации setuptools](https://python-all.ru/3.11/library/importlib.metadata.html).126127*Примечание о совместимости*128129«Выбираемые» точки входа были введены в `importlib_metadata` 3.6 и Python 3.10. До этих изменений `entry_points` не принимал параметров и всегда возвращал словарь точек входа, сгруппированных по группе. Для совместимости, если в entry\_points не переданы параметры, возвращается объект `SelectableGroups`, реализующий интерфейс словаря. В будущем вызов `entry_points` без параметров будет возвращать объект `EntryPoints`. Пользователям следует полагаться на интерфейс выбора для получения точек входа по группе.130131### Метаданные дистрибутива132133Каждый [дистрибутивный пакет](https://python-all.ru/3.11/library/importlib.metadata.html) содержит некоторые метаданные, которые можно извлечь с помощью функции `metadata()`:134135```python136>>> wheel_metadata = metadata('wheel') 137```138139Ключи возвращаемой структуры данных, `PackageMetadata`, определяют ключевые слова метаданных, а значения возвращаются неразобранными из метаданных дистрибутива:140141```python142>>> wheel_metadata['Requires-Python'] 143'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'144```145146`PackageMetadata` также предоставляет атрибут `json`, который возвращает все метаданные в JSON-совместимой форме согласно [**PEP 566**](https://python-all.ru/3.11/library/importlib.metadata.html):147148```python149>>> wheel_metadata.json['requires_python']150'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'151```152153> **Примечание**154>155> Фактический тип объекта, возвращаемого `metadata()`, является деталью реализации, и к нему следует обращаться только через интерфейс, описанный [протоколом PackageMetadata](https://python-all.ru/3.11/library/importlib.metadata.html).156157Изменено в версии 3.10: Теперь `Description` включается в метаданные при представлении через полезную нагрузку (payload). Символы продолжения строки удалены.158159Добавлен атрибут `json`.160161### Версии дистрибутивов162163Функция `version()` – это самый быстрый способ получить номер [версии пакета дистрибутива](https://python-all.ru/3.11/library/importlib.metadata.html) в виде строки:164165```python166>>> version('wheel') 167'0.32.3'168```169170### Файлы дистрибутива171172Также можно получить полный набор файлов, содержащихся в дистрибутиве. Функция `files()` принимает имя [дистрибутива](https://python-all.ru/3.11/library/importlib.metadata.html) и возвращает все файлы, установленные этим дистрибутивом. Каждый возвращаемый файловый объект является `PackagePath`, объектом, производным от [`pathlib.PurePath`](https://python-all.ru/3.11/library/pathlib.html#pathlib.PurePath), с дополнительными свойствами `dist`, `size` и `hash`, как указано в метаданных. Например:173174```python175>>> util = [p for p in files('wheel') if 'util.py' in str(p)][0] 176>>> util 177PackagePath('wheel/util.py')178>>> util.size 179859180>>> util.dist 181<importlib.metadata._hooks.PathDistribution object at 0x101e0cef0>182>>> util.hash 183<FileHash mode: sha256 value: bYkw5oMccfazVCoYQwKkkemoVyMAFoR34mmKBx8R1NI>184```185186Получив файл, можно также прочитать его содержимое:187188```python189>>> print(util.read_text()) 190import base64191import sys192...193def as_bytes(s):194 if isinstance(s, text_type):195 return s.encode('utf-8')196 return s197```198199Также можно использовать метод `locate`, чтобы получить абсолютный путь к файлу:200201```python202>>> util.locate() 203PosixPath('/home/gustav/example/lib/site-packages/wheel/util.py')204```205206В случае, если файл метаданных со списком файлов (RECORD или SOURCES.txt) отсутствует, `files()` вернёт `None`. Вызывающий код может обернуть вызовы `files()` в [always\_iterable](https://python-all.ru/3.11/library/importlib.metadata.html) или иным образом защититься от этой ситуации, если неизвестно, что целевой дистрибутив содержит метаданные.207208### Зависимости дистрибутивов209210Чтобы получить полный набор зависимостей для [дистрибутивного пакета](https://python-all.ru/3.11/library/importlib.metadata.html), используйте функцию `requires()`:211212```python213>>> requires('wheel') 214["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]215```216217### Отображение импортов на дистрибутивы218219Удобный метод для разрешения имени [дистрибутивного пакета](https://python-all.ru/3.11/library/importlib.metadata.html) (или имён, в случае пакета пространства имён), который предоставляет каждый импортируемый модуль или [импортируемый пакет](https://python-all.ru/3.11/library/importlib.metadata.html) верхнего уровня:220221```python222>>> packages_distributions()223{'importlib_metadata': ['importlib-metadata'], 'yaml': ['PyYAML'], 'jaraco': ['jaraco.classes', 'jaraco.functools'], ...}224```225226Новое в версии 3.10.227228## Дистрибутивы229230Хотя вышеописанный API является наиболее распространённым и удобным способом использования, всю эту информацию можно получить из класса `Distribution`. `Distribution` – это абстрактный объект, представляющий метаданные для [дистрибутивного пакета](https://python-all.ru/3.11/library/importlib.metadata.html) Python. Можно получить экземпляр `Distribution`:231232```python233>>> from importlib.metadata import distribution 234>>> dist = distribution('wheel') 235```236237Таким образом, альтернативный способ получить номер версии – через экземпляр `Distribution`:238239```python240>>> dist.version 241'0.32.3'242```243244На экземпляре `Distribution` доступны всевозможные дополнительные метаданные:245246```python247>>> dist.metadata['Requires-Python'] 248'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'249>>> dist.metadata['License'] 250'MIT'251```252253Полный набор доступных метаданных здесь не описан. Дополнительные сведения см. в [спецификациях основных метаданных](https://python-all.ru/3.11/library/importlib.metadata.html).254255## Обнаружение дистрибутивов256257По умолчанию этот пакет предоставляет встроенную поддержку поиска метаданных для [дистрибутивных пакетов](https://python-all.ru/3.11/library/importlib.metadata.html) файловой системы и zip-файлов. Поиск метаданных по умолчанию использует `sys.path`, но трактует эти значения немного иначе, чем другие механизмы импорта. В частности:258259- `importlib.metadata` не учитывает объекты [`bytes`](https://python-all.ru/3.11/library/stdtypes.html#bytes) из `sys.path`.260- `importlib.metadata` случайно будет учитывать объекты [`pathlib.Path`](https://python-all.ru/3.11/library/pathlib.html#pathlib.Path) из `sys.path`, хотя такие значения игнорируются при импорте.261262## Расширение алгоритма поиска263264Поскольку метаданные [дистрибутивного пакета](https://python-all.ru/3.11/library/importlib.metadata.html) недоступны через поиск [`sys.path`](https://python-all.ru/3.11/library/sys.html#sys.path) или напрямую через загрузчики пакетов, метаданные дистрибутива находятся через [искатели](https://python-all.ru/3/reference/import.html#finders-and-loaders) системы импорта. Чтобы найти метаданные дистрибутивного пакета, `importlib.metadata` запрашивает список [искателей метапути](https://python-all.ru/3.11/glossary.html#term-meta-path-finder) на [`sys.meta_path`](https://python-all.ru/3.11/library/sys.html#sys.meta_path).265266По умолчанию `importlib.metadata` устанавливает находильщик для дистрибутивных пакетов, найденных в файловой системе. Этот находильщик на самом деле не находит никакие *дистрибутивы*, но может находить их метаданные.267268Абстрактный класс [`importlib.abc.MetaPathFinder`](https://python-all.ru/3.11/library/importlib.html#importlib.abc.MetaPathFinder) определяет интерфейс, ожидаемый от искателей системой импорта Python. `importlib.metadata` расширяет этот протокол, проверяя наличие опционального вызываемого объекта `find_distributions` у искателей из [`sys.meta_path`](https://python-all.ru/3.11/library/sys.html#sys.meta_path), и предоставляет этот расширенный интерфейс как абстрактный базовый класс `DistributionFinder`, который определяет следующий абстрактный метод:269270```python271@abc.abstractmethod272def find_distributions(context=DistributionFinder.Context()):273 """Возвращает итерируемый объект со всеми экземплярами Distribution, способными274 загружать метаданные для пакетов для указанного ``context``.275 """276```277278Объект `DistributionFinder.Context` предоставляет свойства `.path` и `.name`, указывающие путь для поиска и имя для сопоставления, а также может предоставлять другой релевантный контекст.279280На практике это означает, что для поддержки поиска метаданных дистрибутивного пакета в местах, отличных от файловой системы, нужно создать подкласс `Distribution` и реализовать абстрактные методы. Затем из пользовательского находильщика возвращать экземпляры этого производного `Distribution` в методе `find_distributions()`.281