Spec-Zone.ru › Python 3.8

Использование importlib.metadata

Новая в версии 3.8.

Исходный код: Lib/importlib/metadata.py

Примечание

Данная функциональность является предварительной и может отличаться от обычных семантик версий стандартной библиотеки.

importlib.metadata — это библиотека, предоставляющая доступ к метаданным установленных пакетов. Основанная частично на системе импорта Python, эта библиотека предназначена для замены аналогичной функциональности в API точек входа и API метаданных pkg_resources. Вместе с importlib.resources в Python 3.7 и новее (переносится обратно как importlib_resources для более старых версий Python), это позволяет избежать необходимости использования устаревшего и менее эффективного pkg_resources пакета.

Под «установленным пакетом» обычно понимается сторонний пакет, установленный в каталоге Python site-packages с помощью инструментов, таких как pip. Конкретно, это пакет с обнаруживаемой dist-info или egg-info директорией, и метаданные, определённые в PEP 566 или в его более ранних спецификациях. По умолчанию метаданные пакета могут храниться в файловой системе или в zip-архивах в sys.path. С помощью механизма расширения метаданные могут храниться практически где угодно.

Обзор

Предположим, вы хотите получить строку версии пакета, установленного с помощью pip. Мы начинаем с создания виртуальной среды и установки в неё чего-либо:

$ python3 -m venv example
$ source example/bin/activate
(example) $ 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() для разрешения значения.

>>> eps = entry_points()  
>>> list(eps)  
['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation']
>>> scripts = eps['console_scripts']  
>>> wheel = [ep for ep in scripts if ep.name == 'wheel'][0]  
>>> wheel  
EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')
>>> main = wheel.load()  
>>> main  
<function main at 0x103528488>

group и name — произвольные значения, определённые автором пакета, и обычно клиент захочет разрешить все точки входа для определённой группы. Для получения дополнительной информации о точках входа, их определении и использовании прочитайте документацию setuptools.

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

Каждый дистрибутив включает в себя некоторые метаданные, которые можно извлечь с помощью функции metadata():

>>> wheel_metadata = metadata('wheel')  

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

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

Версии дистрибутива

Функция version() — самый быстрый способ получить номер версии дистрибутива в виде строки:

>>> version('wheel')  
'0.32.3'

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

Вы также можете получить полный набор файлов, содержащихся в дистрибутиве. Функция files() принимает имя пакета дистрибутива и возвращает все файлы, установленные этим дистрибутивом. Каждый возвращённый объект файла — PackagePath, объект, производный от pathlib.Path, с дополнительными свойствами 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

В случае отсутствия файла метаданных со списком файлов (RECORD или SOURCES.txt), files() вернёт None. Звонящий может захотеть обернуть вызовы files() в always_iterable или каким-либо другим способом защититься от этого условия, если известно, что у целевого дистрибутива отсутствуют указанные метаданные.

Требования дистрибутива

Для получения полного набора требований к дистрибутиву используйте функцию requires():

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

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

Хотя приведенный выше 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'

Полный набор доступных метаданных здесь не описан. Дополнительные детали см. в PEP 566.

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

Поскольку метаданные пакета недоступны через sys.path или непосредственно через загрузчики пакетов, метаданные пакета находятся с помощью поисковиков системы импорта. Чтобы найти метаданные пакета дистрибутива, importlib.metadata запрашивает список поисковиков метапути по sys.meta_path.

По умолчанию PathFinder для Python включает в себя обработку, которая вызывает importlib.metadata.MetadataPathFinder для поиска дистрибутивов, загруженных из типичных путей на основе файловой системы.

Абстрактный класс 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().

Примечания

1

Технически, возвращаемый объект метаданных дистрибутива — экземпляр email.message.EmailMessage, но это деталь реализации, а не часть стабильного API. Для доступа к содержимому метаданных следует использовать только методы и синтаксис, подобные методам словаря.

© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/importlib.metadata.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API