# `importlib.metadata` -- パッケージメタデータへのアクセス

Added in version 3.8.

バージョン 3.10 で変更: `importlib.metadata` は暫定的なものではなくなりました。

ソースコード: Lib/importlib/metadata/__init__.py

`importlib.metadata` はインストールされた 配布パッケージ のエントリポイントやトップレベル名 (あれば、 パッケージ やモジュール) のようなメタデータへのアクセスを提供するライブラリです。Pythonのインポートシステムをベースに構築されており、このライブラリは `pkg_resources` の entry point API と metadata API にある同様の機能を置き換えることを目的としています。`importlib.resources` と共に、このパッケージは古くて効率の悪い `pkg_resources` パッケージを使う必要性を無くすことができます。

`importlib.metadata` は、Pythonの `site-packages` ディレクトリに pip などのツールでインストールしたサードパーティの 配布パッケージ に対して動作します。具体的には、 `dist-info` や `egg-info` ディレクトリを持つ配布物や、 コアとなるメタデータの仕様 で定義されたメタデータを検出できるようにします。

重要

These are not necessarily equivalent to or correspond 1:1 with the top-level import package names that can be imported inside Python code. One distribution package can contain multiple import packages (and single modules), and one top-level import package may map to multiple distribution packages if it is a namespace package. You can use package_distributions() to get a mapping between them.

デフォルトでは、配布物のメタデータはファイルシステム上、または `sys.path` のzipアーカイブに保存されます。拡張機構により、メタデータはほとんどどこにでも置くことができます。

参考

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` などのエントリポイントのプロパティ(通常は 'group' や 'name' )で選択可能なエントリポイントの集合を取得することができます。 各グループは エントリポイント オブジェクトの集合を含んでいます。

ディストリビューションのメタデータ を取得することができます。:

    >>> 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` は `.name`, `.group`, `.value` 属性と値を解決する `.load()` メソッドを持っています。 また、 `.value` 属性の構成要素を取得するための `.module`, `.attr`, `.extras` 属性が存在します。

すべてのエントリポイントに問い合わせる:

    >>> eps = entry_points()

`entry_points()` 関数は、すべての `EntryPoint` オブジェクトを集めた `EntryPoints` オブジェクトを、便宜上 `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')

Equivalently, since `entry_points` passes keyword arguments through to select:

    >>> 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のドキュメント を参照してください。

Compatibility Note

The "selectable" entry points were introduced in `importlib_metadata` 3.6 and Python 3.10. Prior to those changes, `entry_points` accepted no parameters and always returned a dictionary of entry points, keyed by group. With `importlib_metadata` 5.0 and Python 3.12, `entry_points` always returns an `EntryPoints` object. See backports.entry_points_selectable for compatibility options.

### 配布物メタデータ

すべての 配布パッケージ にはメタデータが含まれており、 `metadata()` 関数を使って取得することができます:

    >>> wheel_metadata = metadata('wheel')

返されたデータ構造である `PackageMetadata` のキーはメタデータのキーワードを表し、値は配布パッケージのメタデータから解析されずに返されます:

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

`PackageMetadata` には `json` 属性があり、 PEP 566 に従ってすべてのメタデータをJSON互換の形式で返します:

    >>> 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')

In the case where the metadata file listing files (RECORD or SOURCES.txt) is missing, `files()` will return `None`. The caller may wish to wrap calls to `files()` in always_iterable or otherwise guard against this condition if the target distribution is not known to have the metadata present.

### 配布物の要件

配布パッケージ に必要なすべての要件を取得するには、 `requires()` 関数を使用します:

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

### Mapping import to distribution packages

インポート可能なトップレベルのPythonモジュールまたは パッケージ を提供する 配布パッケージ 名(名前空間パッケージの場合はその名前)を解決する便利なメソッドです:

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

Some editable installs, do not supply top-level names, and thus this function is not reliable with such installs.

Added in version 3.10.

## Distributions

上記の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'

利用可能なメタデータのフルセットは、ここでは説明しません。詳細は コアとなるメタデータの仕様 を参照してください。

## Distribution Discovery

デフォルトでは、このパッケージは組み込みで、ファイルシステムおよび zip ファイル 配布パッケージ のメタデータを発見するためのサポートを提供します。このメタデータ検索のデフォルトは `sys.path` ですが、その値をどのように解釈するかは、他のインポート機構が行う方法とは若干異なります。具体的には:

- `importlib.metadata` は `sys.path` の `bytes` オブジェクトを受け入れません。

- `importlib.metadata` は、インポート時には無視されますが、 `sys.path` 上の `pathlib.Path` オブジェクトを優先的に使用します。

## 検索アルゴリズムの拡張

Because Distribution Package metadata is not available through `sys.path` searches, or package loaders directly, the metadata for a distribution is found through import system finders. To find a distribution package's metadata, `importlib.metadata` queries the list of meta path finders on `sys.meta_path`.

By default `importlib.metadata` installs a finder for distribution packages found on the file system. This finder doesn't actually find any distributions, but it can find their metadata.

抽象クラス `importlib.abc.MetaPathFinder` はPythonの importシステムによってファインダーに期待されるインターフェイスを定義しています。 `importlib.metadata` はこのプロトコルを拡張し、 `sys.meta_path` からファインダーにオプションの `find_distributions` を呼び出すことができるようにし、この拡張インターフェースを `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` をサブクラス化して抽象メソッドを実装します。そして、カスタムファインダーから `find_distributions()` メソッドで、派生した `Distribution` のインスタンスを返します。