> **Источник:** https://python-all.ru/3.12/library/importlib.metadata.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

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

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

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

**Исходный код:** [Lib/importlib/metadata/\_\_init\_\_.py](https://python-all.ru/src/3.12/Lib/importlib/metadata/__init__.py)

`importlib.metadata` – библиотека, предоставляющая доступ к метаданным [установленного дистрибутивного пакета (Distribution Package)](https://python-all.ru/3.12/library/importlib.metadata.html), например, к его точкам входа (entry points) или именам верхнего уровня ([импортируемые пакеты (Import Package)](https://python-all.ru/3.12/library/importlib.metadata.html), модули, если они есть). Основанная на системе импорта Python, эта библиотека призвана заменить аналогичную функциональность из [API точек входа](https://python-all.ru/3.12/library/importlib.metadata.html) и [API метаданных](https://python-all.ru/3.12/library/importlib.metadata.html) из `pkg_resources`. Вместе с [`importlib.resources`](https://python-all.ru/3.12/library/importlib.resources.html#module-importlib.resources) этот пакет позволяет отказаться от использования более старого и менее эффективного пакета `pkg_resources`.

`importlib.metadata` работает со сторонними *дистрибутивными пакетами*, установленными в каталог `site-packages` Python с помощью таких инструментов, как [pip](https://python-all.ru/3.12/library/importlib.metadata.html). В частности, он работает с дистрибутивами, имеющими обнаруживаемые каталоги `dist-info` или `egg-info`, и метаданными, определёнными [спецификациями основных метаданных](https://python-all.ru/3.12/library/importlib.metadata.html).

> **Важно**
>
> Они *не обязательно* эквивалентны или соответствуют 1:1 именам верхнего уровня *импортируемых пакетов*, которые можно импортировать в коде Python. Один *дистрибутивный пакет* может содержать несколько *импортируемых пакетов* (и отдельных модулей), а один *импортируемый пакет* верхнего уровня может соответствовать нескольким *дистрибутивным пакетам*, если это пакет пространства имен. Для получения соответствия между ними можно использовать [package\_distributions()](https://python-all.ru/3.12/library/importlib.metadata.html#package-distributions).

По умолчанию метаданные дистрибутива могут располагаться в файловой системе или в zip-архивах на [`sys.path`](https://python-all.ru/3.12/library/sys.html#sys.path). Благодаря механизму расширений метаданные могут находиться практически где угодно.

> **См. также**
>
> **[https://importlib-metadata.readthedocs.io/](https://python-all.ru/3.12/library/importlib.metadata.html)**
>
> Документация для `importlib_metadata`, который предоставляет обратный порт `importlib.metadata`. Она включает [справочник API](https://python-all.ru/3.12/library/importlib.metadata.html) для классов и функций этого модуля, а также [руководство по миграции](https://python-all.ru/3.12/library/importlib.metadata.html) для существующих пользователей `pkg_resources`.

## Обзор

Допустим, нужно получить строку версии для [дистрибутивного пакета](https://python-all.ru/3.12/library/importlib.metadata.html), установленного с помощью `pip`. Начнём с создания виртуального окружения и установки чего-нибудь в него:

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

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

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

Также можно получить набор точек входа, выбираемых по свойствам EntryPoint (обычно «group» или «name»), например, `console_scripts`, `distutils.commands` и другие. Каждая группа содержит набор объектов [EntryPoint](https://python-all.ru/3.12/library/importlib.metadata.html#entry-points).

Вы можете получить [метаданные для дистрибутива](https://python-all.ru/3.12/library/importlib.metadata.html#metadata):

```python
>>> 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']
```

Вы также можете получить [номер версии дистрибутива](https://python-all.ru/3.12/library/importlib.metadata.html#version), перечислить его [составные файлы](https://python-all.ru/3.12/library/importlib.metadata.html#files) и получить список [зависимостей дистрибутива](https://python-all.ru/3.12/library/importlib.metadata.html#requirements).

#### `exception importlib.metadata.PackageNotFoundError`

Подкласс [`ModuleNotFoundError`](https://python-all.ru/3.12/library/exceptions.html#ModuleNotFoundError), вызываемый несколькими функциями в этом модуле при запросе дистрибутивного пакета, который не установлен в текущем окружении Python.

## Функциональное API

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

### Точки входа

#### `importlib.metadata.entry_points(**select_params)`

Возвращает экземпляр [`EntryPoints`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.EntryPoints), описывающий точки входа для текущего окружения. Любые заданные именованные параметры передаются методу `select()` для сравнения с атрибутами отдельных определений точек входа.

Примечание: в настоящее время невозможно запрашивать точки входа на основе их атрибута `EntryPoint.dist` (поскольку разные экземпляры `Distribution` в настоящее время не сравниваются как равные, даже если они имеют одинаковые атрибуты)

#### `class importlib.metadata.EntryPoints`

Подробности о коллекции установленных точек входа.

Также предоставляет атрибут `.groups`, который сообщает все идентифицированные группы точек входа, и атрибут `.names`, который сообщает все идентифицированные имена точек входа.

#### `class importlib.metadata.EntryPoint`

Подробности об установленной точке входа.

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

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

```python
>>> eps = entry_points()
```

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

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

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

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

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

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

Выбрать конкретный скрипт с именем «wheel» (находится в проекте wheel):

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

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

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

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

```python
>>> 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](https://python-all.ru/3.12/library/importlib.metadata.html).

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

«Выбираемые» (selectable) точки входа были введены в `importlib_metadata` 3.6 и Python 3.10. До этих изменений `entry_points` не принимал параметров и всегда возвращал словарь точек входа, сгруппированных по группам. В версии `importlib_metadata` 5.0 и Python 3.12 `entry_points` всегда возвращает объект `EntryPoints`. Смотрите [backports.entry\_points\_selectable](https://python-all.ru/3.12/library/importlib.metadata.html) для вариантов обеспечения совместимости.

### Метаданные дистрибутива

#### `importlib.metadata.metadata(distribution_name)`

Возвращает метаданные дистрибутива для указанного пакета дистрибутива в виде экземпляра [`PackageMetadata`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.PackageMetadata).

Вызывает [`PackageNotFoundError`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.PackageNotFoundError), если именованный дистрибутивный пакет не установлен в текущем окружении Python.

#### `class importlib.metadata.PackageMetadata`

Конкретная реализация протокола [PackageMetadata](https://python-all.ru/3.12/library/importlib.metadata.html).

В дополнение к предоставлению определённых методов и атрибутов протокола, обращение к экземпляру по индексу эквивалентно вызову метода `get()`.

Каждый [пакет дистрибутива](https://python-all.ru/3.12/library/importlib.metadata.html) содержит метаданные, которые можно извлечь с помощью функции `metadata()`:

```python
>>> wheel_metadata = metadata('wheel')
```

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

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

[`PackageMetadata`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.PackageMetadata) также предоставляет атрибут `json`, который возвращает все метаданные в JSON-совместимой форме согласно [**PEP 566**](https://python-all.ru/3.12/library/importlib.metadata.html):

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

Полный набор доступных метаданных здесь не описывается. За дополнительными сведениями обратитесь к [спецификации основных метаданных PyPA](https://python-all.ru/3.12/library/importlib.metadata.html).

Изменено в версии 3.10: Теперь `Description` включается в метаданные при представлении через полезную нагрузку (payload). Символы продолжения строки удалены.

Добавлен атрибут `json`.

### Версии дистрибутивов

#### `importlib.metadata.version(distribution_name)`

Возвращает [версию](https://python-all.ru/3.12/library/importlib.metadata.html) установленного пакета дистрибутива для указанного пакета дистрибутива.

Вызывает [`PackageNotFoundError`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.PackageNotFoundError), если именованный дистрибутивный пакет не установлен в текущем окружении Python.

Функция `version()` – это самый быстрый способ получить номер [версии пакета дистрибутива](https://python-all.ru/3.12/library/importlib.metadata.html) в виде строки:

```python
>>> version('wheel')
'0.32.3'
```

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

#### `importlib.metadata.files(distribution_name)`

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

Вызывает [`PackageNotFoundError`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.PackageNotFoundError), если именованный дистрибутивный пакет не установлен в текущем окружении Python.

Возвращает [`None`](https://python-all.ru/3.12/library/constants.html#None), если дистрибутив найден, но в базе данных установки отсутствуют записи, сообщающие о файлах, связанных с этим пакетом.

#### `class importlib.metadata.PackagePath`

Объект, производный от [`pathlib.PurePath`](https://python-all.ru/3.12/library/pathlib.html#pathlib.PurePath), с дополнительными свойствами `dist`, `size` и `hash`, соответствующими метаданным установки пакета дистрибутива для этого файла.

Функция `files()` принимает имя [дистрибутивного пакета](https://python-all.ru/3.12/library/importlib.metadata.html) и возвращает все файлы, установленные этим дистрибутивом. Каждый файл представлен как экземпляр [`PackagePath`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.PackagePath). Например:

```python
>>> 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>
```

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

```python
>>> 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()`, чтобы получить абсолютный путь к файлу:

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

Если файл метаданных со списком файлов (`RECORD` или `SOURCES.txt`) отсутствует, `files()` вернёт [`None`](https://python-all.ru/3.12/library/constants.html#None). Вызывающий код может обернуть вызовы `files()` в [always\_iterable](https://python-all.ru/3.12/library/importlib.metadata.html) или иным образом защититься от такой ситуации, если неизвестно, что целевой дистрибутив содержит эти метаданные.

### Зависимости дистрибутивов

#### `importlib.metadata.requires(distribution_name)`

Возвращает объявленные спецификаторы зависимостей для именованного дистрибутивного пакета.

Вызывает [`PackageNotFoundError`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.PackageNotFoundError), если именованный дистрибутивный пакет не установлен в текущем окружении Python.

Чтобы получить полный набор зависимостей для [дистрибутивного пакета](https://python-all.ru/3.12/library/importlib.metadata.html), используйте функцию `requires()`:

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

### Отображение импортов на дистрибутивы

#### `importlib.metadata.packages_distributions()`

Возвращает отображение имён модулей верхнего уровня и импортируемых пакетов, найденных с помощью [`sys.meta_path`](https://python-all.ru/3.12/library/sys.html#sys.meta_path), на имена дистрибутивных пакетов (если таковые есть), предоставляющих соответствующие файлы.

Для поддержки пакетов пространств имён (которые могут содержать компоненты от нескольких дистрибутивов) каждое имя импорта верхнего уровня сопоставляется со списком имён дистрибутивов, а не напрямую с одним именем.

Удобный метод для разрешения имени [дистрибутивного пакета](https://python-all.ru/3.12/library/importlib.metadata.html) (или имён, в случае пакета пространства имён), который предоставляет каждый импортируемый модуль или [импортируемый пакет](https://python-all.ru/3.12/library/importlib.metadata.html) верхнего уровня:

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

Некоторые редактируемые установки [не предоставляют имён верхнего уровня](https://python-all.ru/3.12/library/importlib.metadata.html), поэтому эта функция не является надёжной для таких установок.

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

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

#### `importlib.metadata.distribution(distribution_name)`

Возвращает экземпляр [`Distribution`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.Distribution), описывающий именованный дистрибутивный пакет.

Вызывает [`PackageNotFoundError`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.PackageNotFoundError), если именованный дистрибутивный пакет не установлен в текущем окружении Python.

#### `class importlib.metadata.Distribution`

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

Примечание: разные экземпляры `Distribution` в настоящее время не считаются равными, даже если они относятся к одному и тому же установленному дистрибутиву и, соответственно, имеют одинаковые атрибуты.

Хотя описанный выше API на уровне модуля является наиболее распространённым и удобным, всю эту информацию можно получить из класса `Distribution`. `Distribution` – это абстрактный объект, представляющий метаданные [дистрибутивного пакета](https://python-all.ru/3.12/library/importlib.metadata.html) Python. Конкретный экземпляр подкласса `Distribution` для установленного дистрибутивного пакета можно получить, вызвав функцию [`distribution()`](https://python-all.ru/3.12/library/importlib.metadata.html#importlib.metadata.distribution):

```python
>>> from importlib.metadata import distribution
>>> dist = distribution('wheel')
>>> type(dist)
<class 'importlib.metadata.PathDistribution'>
```

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

```python
>>> dist.version
'0.32.3'
```

На экземплярах `Distribution` доступны самые разные дополнительные метаданные:

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

Полный набор доступных метаданных здесь не описывается. За дополнительными сведениями обратитесь к [спецификации основных метаданных PyPA](https://python-all.ru/3.12/library/importlib.metadata.html).

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

По умолчанию этот пакет предоставляет встроенную поддержку поиска метаданных для [дистрибутивных пакетов](https://python-all.ru/3.12/library/importlib.metadata.html) файловой системы и zip-файлов. Поиск метаданных по умолчанию использует `sys.path`, но трактует эти значения немного иначе, чем другие механизмы импорта. В частности:

- `importlib.metadata` не учитывает объекты [`bytes`](https://python-all.ru/3.12/library/stdtypes.html#bytes) из `sys.path`.
- `importlib.metadata` случайно будет учитывать объекты [`pathlib.Path`](https://python-all.ru/3.12/library/pathlib.html#pathlib.Path) из `sys.path`, хотя такие значения игнорируются при импорте.

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

Поскольку метаданные [дистрибутивного пакета](https://python-all.ru/3.12/library/importlib.metadata.html) недоступны через поиск [`sys.path`](https://python-all.ru/3.12/library/sys.html#sys.path) или напрямую через загрузчики пакетов, метаданные дистрибутива находятся с помощью [находильщиков (finders)](https://python-all.ru/3.12/reference/import.html#finders-and-loaders) системы импорта. Чтобы найти метаданные дистрибутивного пакета, `importlib.metadata` опрашивает список [находильщиков мета-пути (meta path finders)](https://python-all.ru/3.12/glossary.html#term-meta-path-finder) на [`sys.meta_path`](https://python-all.ru/3.12/library/sys.html#sys.meta_path).

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

Абстрактный класс [`importlib.abc.MetaPathFinder`](https://python-all.ru/3.12/library/importlib.html#importlib.abc.MetaPathFinder) определяет интерфейс, ожидаемый от искателей системой импорта Python. `importlib.metadata` расширяет этот протокол, проверяя наличие опционального вызываемого объекта `find_distributions` у искателей из [`sys.meta_path`](https://python-all.ru/3.12/library/sys.html#sys.meta_path), и предоставляет этот расширенный интерфейс как абстрактный базовый класс `DistributionFinder`, который определяет следующий абстрактный метод:

```python
@abc.abstractmethod
def find_distributions(context=DistributionFinder.Context()):
    """Возвращает итерируемый объект со всеми экземплярами Distribution, способными
    загружать метаданные для пакетов для указанного ``context``.
    """
```

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

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