Документация Python неофициальный перевод

importlib.metadata.md

258 строк · 17.5 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.10/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.10/Lib/importlib/metadata/__init__.py)1415`importlib.metadata` – это библиотека, обеспечивающая доступ к метаданным установленных пакетов. Частично основанная на системе импорта Python, эта библиотека призвана заменить аналогичную функциональность в [точки входа API](https://python-all.ru/3.10/library/importlib.metadata.html) и [API метаданных](https://python-all.ru/3.10/library/importlib.metadata.html) из `pkg_resources`. Вместе с [`importlib.resources`](https://python-all.ru/3.10/library/importlib.html#module-importlib.resources) (начиная с Python 3.7 и новее, с обратным портированием как [importlib\_resources](https://python-all.ru/3.10/library/importlib.metadata.html) для более старых версий Python), это позволяет отказаться от использования устаревшего и менее эффективного пакета `pkg_resources`.1617Под «установленным пакетом» обычно понимается сторонний пакет, установленный в каталог `site-packages` Python с помощью таких инструментов, как [pip](https://python-all.ru/3.10/library/importlib.metadata.html). В частности, это пакет, имеющий либо обнаруживаемый каталог `dist-info` или `egg-info` и метаданные, определённые [**PEP 566**](https://python-all.ru/3.10/library/importlib.metadata.html) или более старыми спецификациями. По умолчанию метаданные пакета могут находиться в файловой системе или в zip-архивах на [`sys.path`](https://python-all.ru/3.10/library/sys.html#sys.path). Благодаря механизму расширения метаданные могут находиться практически где угодно.1819## Обзор2021Предположим, вы хотите получить строку версии для пакета, установленного с помощью `pip`. Начнём с создания виртуального окружения и установки чего-нибудь в него:2223```console24$ python -m venv example25$ source example/bin/activate26(example) $ pip install wheel27```2829Вы можете получить строку версии для `wheel`, выполнив следующее:3031```pycon32(example) $ python33>>> from importlib.metadata import version  34>>> version('wheel')  35'0.32.3'36```3738Также можно получить набор точек входа, разбитых по группам, таких как `console_scripts`, `distutils.commands` и другие. Каждая группа содержит последовательность объектов [EntryPoint](https://python-all.ru/3.10/library/importlib.metadata.html#entry-points).3940Вы можете получить [метаданные для дистрибутива](https://python-all.ru/3.10/library/importlib.metadata.html#metadata):4142```python43>>> list(metadata('wheel'))  44['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']45```4647Вы также можете получить [номер версии дистрибутива](https://python-all.ru/3.10/library/importlib.metadata.html#version), перечислить его [составные файлы](https://python-all.ru/3.10/library/importlib.metadata.html#files) и получить список [зависимостей дистрибутива](https://python-all.ru/3.10/library/importlib.metadata.html#requirements).4849## Функциональное API5051Этот пакет предоставляет следующие функции через свой публичный API.5253### Точки входа5455Функция `entry_points()` возвращает коллекцию точек входа. Точки входа представлены экземплярами `EntryPoint`; каждый `EntryPoint` имеет атрибуты `.name`, `.group` и `.value`, а также метод `.load()` для получения значения. Также есть атрибуты `.module`, `.attr` и `.extras` для получения компонентов атрибута `.value`.5657Запрос всех точек входа:5859```python60>>> eps = entry_points()  61```6263Функция `entry_points()` возвращает объект `EntryPoints`, последовательность всех объектов `EntryPoint` с атрибутами `names` и `groups` для удобства:6465```python66>>> sorted(eps.groups)  67['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation']68```6970`EntryPoints` имеет метод `select` для выбора точек входа, соответствующих определённым свойствам. Выберите точки входа в группе `console_scripts`:7172```python73>>> scripts = eps.select(group='console_scripts')  74```7576Аналогично, поскольку `entry_points` передаёт ключевые аргументы в select:7778```python79>>> scripts = entry_points(group='console_scripts')  80```8182Выбрать конкретный скрипт с именем «wheel» (находится в проекте wheel):8384```python85>>> 'wheel' in scripts.names  86True87>>> wheel = scripts['wheel']  88```8990Аналогично, запросить эту точку входа во время выбора:9192```python93>>> (wheel,) = entry_points(group='console_scripts', name='wheel')  94>>> (wheel,) = entry_points().select(group='console_scripts', name='wheel')  95```9697Проверить разрешённую точку входа:9899```python100>>> wheel  101EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')102>>> wheel.module  103'wheel.cli'104>>> wheel.attr  105'main'106>>> wheel.extras  107[]108>>> main = wheel.load()  109>>> main  110<function main at 0x103528488>111```112113`group` и `name` – произвольные значения, определяемые автором пакета; обычно клиент хочет получить все точки входа для определённой группы. Подробнее о точках входа, их определении и использовании читайте в [документации setuptools](https://python-all.ru/3.10/library/importlib.metadata.html).114115*Примечание о совместимости*116117«Выбираемые» точки входа были введены в `importlib_metadata` 3.6 и Python 3.10. До этих изменений `entry_points` не принимал параметров и всегда возвращал словарь точек входа, сгруппированных по группе. Для совместимости, если в entry\_points не переданы параметры, возвращается объект `SelectableGroups`, реализующий интерфейс словаря. В будущем вызов `entry_points` без параметров будет возвращать объект `EntryPoints`. Пользователям следует полагаться на интерфейс выбора для получения точек входа по группе.118119### Метаданные дистрибутива120121Каждый дистрибутив содержит некоторые метаданные, которые можно извлечь с помощью функции `metadata()`:122123```python124>>> wheel_metadata = metadata('wheel')  125```126127Ключи возвращаемой структуры данных, `PackageMetadata`, определяют ключевые слова метаданных, а значения возвращаются неразобранными из метаданных дистрибутива:128129```python130>>> wheel_metadata['Requires-Python']  131'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'132```133134`PackageMetadata` также предоставляет атрибут `json`, который возвращает все метаданные в JSON-совместимой форме согласно [**PEP 566**](https://python-all.ru/3.10/library/importlib.metadata.html):135136```python137>>> wheel_metadata.json['requires_python']138'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'139```140141Изменено в версии 3.10: Теперь `Description` включается в метаданные при представлении через полезную нагрузку (payload). Символы продолжения строки удалены.142143Новое в версии 3.10: Был добавлен атрибут `json`.144145### Версии дистрибутивов146147Функция `version()` – это самый быстрый способ получить номер версии дистрибутива в виде строки:148149```python150>>> version('wheel')  151'0.32.3'152```153154### Файлы дистрибутива155156Также можно получить полный набор файлов, содержащихся в дистрибутиве. Функция `files()` принимает имя пакета дистрибутива и возвращает все файлы, установленные этим дистрибутивом. Каждый возвращаемый файловый объект – это `PackagePath`, производный объект [`pathlib.PurePath`](https://python-all.ru/3.10/library/pathlib.html#pathlib.PurePath) с дополнительными свойствами `dist`, `size` и `hash`, как указано в метаданных. Например:157158```python159>>> util = [p for p in files('wheel') if 'util.py' in str(p)][0]  160>>> util  161PackagePath('wheel/util.py')162>>> util.size  163859164>>> util.dist  165<importlib.metadata._hooks.PathDistribution object at 0x101e0cef0>166>>> util.hash  167<FileHash mode: sha256 value: bYkw5oMccfazVCoYQwKkkemoVyMAFoR34mmKBx8R1NI>168```169170Получив файл, можно также прочитать его содержимое:171172```python173>>> print(util.read_text())  174import base64175import sys176...177def as_bytes(s):178    if isinstance(s, text_type):179        return s.encode('utf-8')180    return s181```182183Также можно использовать метод `locate`, чтобы получить абсолютный путь к файлу:184185```python186>>> util.locate()  187PosixPath('/home/gustav/example/lib/site-packages/wheel/util.py')188```189190В случае, если файл метаданных со списком файлов (RECORD или SOURCES.txt) отсутствует, `files()` вернёт `None`. Вызывающий код может обернуть вызовы `files()` в [always\_iterable](https://python-all.ru/3.10/library/importlib.metadata.html) или иным образом защититься от этой ситуации, если неизвестно, что целевой дистрибутив содержит метаданные.191192### Зависимости дистрибутивов193194Чтобы получить полный набор зависимостей для дистрибутива, используйте функцию `requires()`:195196```python197>>> requires('wheel')  198["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]199```200201### Дистрибутивы пакетов202203Удобный метод для определения дистрибутива или дистрибутивов (в случае пространства имён пакета) для корневых пакетов или модулей Python:204205```python206>>> packages_distributions()207{'importlib_metadata': ['importlib-metadata'], 'yaml': ['PyYAML'], 'jaraco': ['jaraco.classes', 'jaraco.functools'], ...}208```209210Новое в версии 3.10.211212## Дистрибутивы213214Хотя приведённый выше API является наиболее распространённым и удобным способом использования, всю эту информацию можно получить из класса `Distribution`. `Distribution` – это абстрактный объект, представляющий метаданные для пакета Python. Можно получить экземпляр `Distribution`:215216```python217>>> from importlib.metadata import distribution  218>>> dist = distribution('wheel')  219```220221Таким образом, альтернативный способ получить номер версии – через экземпляр `Distribution`:222223```python224>>> dist.version  225'0.32.3'226```227228На экземпляре `Distribution` доступны всевозможные дополнительные метаданные:229230```python231>>> dist.metadata['Requires-Python']  232'>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'233>>> dist.metadata['License']  234'MIT'235```236237Полный набор доступных метаданных здесь не описан. Подробнее см. [**PEP 566**](https://python-all.ru/3.10/library/importlib.metadata.html) .238239## Расширение алгоритма поиска240241Поскольку метаданные пакета недоступны через поиск [`sys.path`](https://python-all.ru/3.10/library/sys.html#sys.path) или напрямую через загрузчики пакетов, метаданные пакета находятся через систему импорта [искатели](https://python-all.ru/3.10/reference/import.html#finders-and-loaders). Чтобы найти метаданные пакета дистрибутива, `importlib.metadata` запрашивает список [искателей метапути](https://python-all.ru/3.10/glossary.html#term-meta-path-finder) в [`sys.meta_path`](https://python-all.ru/3.10/library/sys.html#sys.meta_path).242243Стандартный `PathFinder` для Python включает хук, который вызывает `importlib.metadata.MetadataPathFinder` для поиска дистрибутивов, загруженных из типичных путей файловой системы.244245Абстрактный класс [`importlib.abc.MetaPathFinder`](https://python-all.ru/3.10/library/importlib.html#importlib.abc.MetaPathFinder) определяет интерфейс, ожидаемый от искателей системой импорта Python. `importlib.metadata` расширяет этот протокол, проверяя наличие опционального вызываемого объекта `find_distributions` у искателей из [`sys.meta_path`](https://python-all.ru/3.10/library/sys.html#sys.meta_path), и предоставляет этот расширенный интерфейс как абстрактный базовый класс `DistributionFinder`, который определяет следующий абстрактный метод:246247```python248@abc.abstractmethod249def find_distributions(context=DistributionFinder.Context()):250    """Возвращает итерируемый объект со всеми экземплярами Distribution, способными251    загружать метаданные для пакетов для указанного ``context``.252    """253```254255Объект `DistributionFinder.Context` предоставляет свойства `.path` и `.name`, указывающие путь для поиска и имя для сопоставления, а также может предоставлять другой релевантный контекст.256257На практике это означает, что для поддержки поиска метаданных дистрибутивного пакета в местах, отличных от файловой системы, нужно создать подкласс `Distribution` и реализовать абстрактные методы. Затем из пользовательского находильщика возвращать экземпляры этого производного `Distribution` в методе `find_distributions()`.258