# 5. インポートシステム

ある 1 つの module にある Python コードから他のモジュールをインポート (importing) することで、そこにあるコードへアクセスできるようになります。 `import` 文はインポート機構を動かす最も一般的な方法ですが、それが唯一の方法ではありません。 `importlib.import_module()` や組み込みの `__import__()` といった関数を使っても、インポート機構を動かすことができます。

`import` 文は 2 つの処理を連続して行っています; ある名前のモジュールを探し、その検索結果をローカルスコープの名前に束縛します。 `import` 文の検索処理は、適切な引数で `__import__()` 関数を呼び出すこととして定義されています。 `__import__()` の戻り値は `import` 文の名前束縛処理の実行で使われます。名前束縛処理の厳密な詳細は `import` 文を参照してください。

`__import__()` を直接呼び出すとモジュールの検索のみが行われ、見つかった場合、モジュールの作成処理が行われます。親パッケージのインポートや (`sys.modules` を含む) 様々なキャッシュの更新などの副作用は起きるかもしれませんが、 `import` 文のみが名前束縛処理を行います。

import 文の一部として `__import__()` を呼び出したときは標準の組み込みの `__import__()` が呼ばれます。インポートシステムを起動する他の機構 (たとえば `importlib.import_module()` など) は、 `__import__()` を覆すことを選んで固有のインポートセマンティクスを実装するための方法を用いることがあります。

モジュールが初めてインポートされるとき、 Python はそのモジュールを検索し、見付かった場合、モジュールオブジェクトを作成し、初期化します 1 。その名前のモジュールが見付からなかった場合、 `ModuleNotFoundError` が送出されます。 Python には、インポート機構が実行されたときに名前からモジュールを検索する様々な戦略が実装されています。これらの戦略は、これ以降の節で解説される様々なフックを使って、修正したり拡張したりできます。

バージョン 3.3 で変更: インポートシステムが PEP 302 の第 2 フェーズの完全な実装へ更新されました。もはや暗黙的なインポート機構はありません - インポート機構全体は `sys.meta_path` を通して公開されています。加えて、ネイティブの名前空間パッケージのサポートは実装されています ( PEP 420 を参照) 。

## 5.1. `importlib`

`importlib` モジュールはインポート機構とやり取りするための便利な API を提供します。例えば `importlib.import_module()` は、インポート機構を実行するための組み込みの `__import__()` よりもシンプルで推奨される API を提供します。より詳細なことは `importlib` ライブラリのドキュメントを参照してください。

## 5.2. パッケージ

Python にはモジュールオブジェクトの種類は 1 種類しかなく、 Python 、 C 、それ以外のもののどれで実装されているかに関係なく、すべてのモジュールはこの種類になります。モジュールの組織化を助け、名前階層を提供するために、 Python には パッケージ という概念があります。

パッケージはファイルシステムのディレクトリ、モジュールはディレクトリにあるファイルと考えることができますが、パッケージやモジュールはファイルシステムから生まれる必要はないので、この比喩を額面通りに受け取ってはいけません。この文書の目的のために、ディレクトリとファイルという便利な比喩を使うことにします。ファイルシステムのディレクトリのように、パッケージは階層構造を成し、通常のモジュールだけでなく、サブパッケージを含むこともあります。

すべてのパッケージはモジュールですが、すべてのモジュールがパッケージとは限らないことを心に留めておくのが重要です。もしくは他の言い方をすると、パッケージは単なる特別な種類のモジュールであると言えます。特に、`__path__` 属性を持つ任意のモジュールはパッケージと見なされます。

すべてのモジュールには名前があります。サブパッケージ名は、 Python の標準の属性アクセスの構文に似て、親パッケージ名とドットで区切られています。したがって、 `sys` と呼ばれるモジュールや `email` と呼ばれるパッケージを見掛けることがあるでしょう。その中には `email.mime` と呼ばれるサブパッケージと、そのサブパッケージの中に `email.mime.text` と呼ばれるモジュールがあります。

### 5.2.1. 通常のパッケージ

Python では、 通常のパッケージ と 名前空間パッケージ の 2 種類のパッケージが定義されています。通常のパッケージは Python 3.2 以前から存在する伝統的なパッケージです。典型的な通常のパッケージは `__init__.py` ファイルを含むディレクトリとして実装されます。通常のパッケージがインポートされたとき、この `__init__.py` ファイルが暗黙的に実行され、それで定義しているオブジェクトがパッケージ名前空間にある名前に束縛されます。 `__init__.py` ファイルは、他のモジュールに書ける Python コードと同じものを含むことができ、モジュールがインポートされたときに Python はモジュールに属性を追加したりします。

例えば、以下のようなファイルシステム配置は、3 つのサブパッケージを持つ最上位の `parent` パッケージを定義します:

    parent/
        __init__.py
        one/
            __init__.py
        two/
            __init__.py
        three/
            __init__.py

`parent.one` をインポートすると暗黙的に `parent/__init__.py` と `parent/one/__init__.py` が実行されます。その後に `parent.two` もしくは `parent.three` をインポートすると、それぞれ `parent/two/__init__.py` や `parent/three/__init__.py` が実行されます。

### 5.2.2. 名前空間パッケージ

名前空間パッケージは様々な ポーション を寄せ集めたもので、それぞれのポーションはサブパッケージを親パッケージに提供します。ポーションはファイルシステムの別々の場所にあることもあります。ポーションは、 zip ファイルの中やネットワーク上や、それ以外のインポート時に Python が探すどこかの場所で見つかることもあります。名前空間パッケージはファイルシステム上のオブジェクトに対応することもあるし、そうでないこともあります; それらは実際の実体のない仮想モジュールです。

名前空間パッケージは、 `__path__` 属性に普通のリストは使いません。その代わりに独自の iterable 型を使っていて、ポーションの親パッケージのパス (もしくは最上位パッケージのための `sys.path`) が変わった場合、そのパッケージでの次のインポートの際に、新たに自動でパッケージポーションを検索します。

名前空間パッケージには `parent/__init__.py` ファイルはありません。それどころか、異なるポーションがそれぞれ提供する複数の `parent` ディレクトリがインポート検索の際に見つかることもあります。したがって `parent/one` は物理的に `parent/two` の隣りにあるとは限りません。その場合、そのパッケージかサブパッケージのうち 1 つがインポートされたとき、Python は最上位の `parent` パッケージのための名前空間パッケージを作成します。

名前空間パッケージの仕様については PEP 420 も参照してください。

## 5.3. 検索

検索を始めるためには、 Python はインポートされるモジュール (もしくはパッケージですが、ここでの議論の目的においてはささいな違いです) の 完全修飾 名を必要とします。この名前は、 `import` 文の様々な引数や `importlib.import_module()` および `__import__()` 関数のパラメータから得られます。

この名前はインポート検索の様々なフェーズで使われ、これは例えば `foo.bar.baz` のようなドットで区切られたサブモジュールへのパスだったりします。この場合、 Python は最初に `foo` を、次に `foo.bar` 、そして最後に `foo.bar.baz` をインポートしようとします。中間のいずれかのインポートに失敗した場合は、 `ModuleNotFoundError` が送出されます。

### 5.3.1. モジュールキャッシュ

インポート検索で最初に調べる場所は `sys.modules` です。このマッピングは、中間のパスを含む、これまでにインポートされたすべてのモジュールのキャッシュを提供します。なので `foo.bar.baz` がインポート済みの場合、 `sys.modules` は `foo` 、 `foo.bar` 、 `foo.bar.baz` のエントリーを含みます。それぞれのキーはその値として対応するモジュールオブジェクトを持ちます。

インポートではモジュール名は `sys.modules` から探され、存在した場合は、対応する値がインポートされるべきモジュールであり、この処理は完了します。しかし値が `None` だった場合、 `ModuleNotFoundError` が送出されます。モジュール名が見付からなかった場合は、 Python はモジュールの検索を続けます。

`sys.modules` は書き込み可能です。キーの削除は対応するモジュールを破壊しない (他のモジュールがそのモジュールへの参照を持っている) かもしれませんが、指定されたモジュールのキャッシュされたエントリーを無効にし、それが次にインポートされたとき Python にそのモジュールを改めて検索させることになります。キーを `None` に対応付けることもできますが、次にそのモジュールがインポートされるときに `ModuleNotFoundError` となってしまいます。

たとえモジュールオブジェクトへの参照を保持しておいて、 `sys.modules` にキャッシュされたエントリーを無効にし、その指定したモジュールを再インポートしたとしても、 2 つのモジュールオブジェクトは同じでは ない ことに注意してください。それとは対照的に、 `importlib.reload()` は 同じ モジュールオブジェクトを再利用し、モジュールのコードを再実行することで単にモジュールの内容を再初期化するだけです。

### 5.3.2. ファインダーとローダー

`sys.modules` に指定されたモジュールが見つからなかった場合は、 Python のインポートプロトコルが起動され、モジュールを見つけロードします。このプロトコルは 2 つの概念的なオブジェクト、 ファインダー と ローダー から成ります。ファインダーの仕事は、知っている戦略を使って指定されたモジュールを見つけられるかどうか判断することです。両方のインターフェースを実装しているオブジェクトは インポーター と呼ばれます - インポーターは要求されたモジュールがロードできると分かったとき、自分自身を返します。

Python にはデフォルトのファインダーとインポーターがいくつかあります。 1 つ目のものは組み込みモジュールの見つけ方を知っていて、 2 つ目のものは凍結されたモジュール (訳注: freeze ツールで処理されたモジュールのこと。 プログラミング FAQ の「どうしたら Python スクリプトからスタンドアロンバイナリを作れますか？」の項目を参照) の見つけ方を知っています。 3 つ目のものは インポートパス からモジュールを探します。 インポートパス はファイルシステムのパスや zip ファイルの位置を示すリストです。このリストは、 URL で特定できるもののような、位置を示すことのできる任意のリソースの検索にまで拡張することもできます。

インポート機構は拡張可能なので、モジュール検索の範囲とスコープを拡張するために新しいファインダーを付け加えることができます。

ファインダーは実際にはモジュールをロードしません。指定されたモジュールが見つかった場合、ファインダーは module spec (モジュール仕様)、すなわちモジュールのインポート関連の情報をカプセル化したものを返します。モジュールのロード時にインポート機構はそれを利用します。

次の節では、インポート機構を拡張するための新しいファインダーやローダーの作成と登録を含め、ファインダーとローダーのプロトコルについてより詳しく解説します。

バージョン 3.4 で変更: Python の以前のバージョンでは、ファインダーは直接 ローダー を返していましたが、現在はローダーを 含む モジュール仕様を返します。ローダーはインポート中はまだ使われていますが、責任は減りました。

### 5.3.3. インポートフック

インポート機構は拡張可能なように設計されています; その主となる仕組みは インポートフック です。インポートフックには 2 種類あります: メタフック と インポートパスフック です。

メタフックはインポート処理の最初、 `sys.modules` キャッシュの検索以外のインポート処理より前に呼び出されます。これにより、 `sys.path` の処理や凍結されたモジュールや組み込みのモジュールでさえも、メタフックで上書きすることができます。メタフックは以下で解説するように、 `sys.meta_path` に新しいファインダーオブジェクトを追加することで登録されます。

インポートパスフックは、 `sys.path` (もしくは `package.__path__`) の処理の一部として、対応するパス要素を取り扱うところで呼び出されます。インポートパスフックは以下で解説するように、新しい呼び出し可能オブジェクトを `sys.path_hooks` に追加することで登録されます。

### 5.3.4. メタパス

指定されたモジュールが `sys.modules` に見つからなかったとき、 Python は次にメタパス・ファインダー・オブジェクトが格納されている `sys.meta_path` を検索します。指定されたモジュールを扱うことができるかどうかを調べるために、各ファインダーに問い合わせを行います。メタパス・ファインダーには、名前とインポートパスと (オプションの) ターゲットモジュールの 3 つの引数を取る `find_spec()` という名前のメソッドが実装されていなければいけません。メタパス・ファインダーでは、指定されたモジュールを扱えるかどうかを判定するための戦略は任意のものを使って構いません。

meta path finder が指定されたモジュールの扱い方を知っている場合は、ファインダは spec オブジェクトを返します。指定されたモジュールを扱えない場合は `None` を返します。 `sys.meta_path` に対する処理が spec を返さずにリストの末尾に到達してしまった場合は、 `ModuleNotFoundError` を送出します。その他の送出された例外はそのまま呼び出し元に伝播され、インポート処理を異常終了させます。

メタパス・ファインダーの `find_spec()` メソッドは 2 つまたは 3 つの引数を渡して呼び出します。1 つ目の引数はインポートされるモジュールの完全修飾名で、例えば `foo.bar.baz` などです。2 つ目の引数はモジュールの検索で使われるパスです。最上位のモジュールでは 2 つ目の引数は `None` にしますが、サブモジュールやサブパッケージでは 2 つ目の引数は親パッケージの `__path__` 属性の値です。適切な `__path__` 属性にアクセスできなかった場合は、 `ModuleNotFoundError` が送出されます。3 つ目の引数は、あとでロードされるターゲットとなる既存のモジュールオブジェクトです。インポートシステムはリロードの間だけターゲットモジュール をセットします。

メタパスは、1 回のインポート要求で複数回走査される可能性があります。例えば、関係するモジュールがどれもまだキャッシュされていないとしたときに `foo.bar.baz` をインポートすると、最初は各メタパス・ファインダー (`mpf`) に対して `mpf.find_spec("foo", None, None)` を呼び出して、最上位のインポート処理を行います。`foo` がインポートされた後に、`mpf.find_spec("foo.bar", foo.__path__, None)` を呼び出していく 2 回目のメタパスの走査が行われ、`foo.bar` がインポートされます。`foo.bar` のインポートまで行われたら、最後の走査で `mpf.find_spec("foo.bar.baz", foo.bar.__path__, None)` を呼び出していきます。

あるメタパス・ファインダーは最上位のインポートのみサポートしています。これらのインポーターは、2 つ目の引数に `None` 以外のものが渡されたとき、常に `None` を返します。

Python のデフォルトの `sys.meta_path` は 3 つのパスファインダーを持っています。組み込みモジュールのインポートの方法を知っているもの、凍結されたモジュールのインポートの方法を知っているもの、 インポートパス からのモジュールのインポートの方法を知っているもの (つまり パスベース・ファインダー) があります。

バージョン 3.4 で変更: メタパス・ファインダーの `find_spec()` メソッドは `find_module()` を置き換えました。 `find_module()` メソッドは deprecated です。それは今でも変更なしに動きますが、インポート機構はファインダーが `find_spec()` を実装していない場合にのみそれを試します。

## 5.4. ロード

モジュール仕様が見つかった場合、インポート機構はモジュールをロードする時にそれ (およびそれに含まれるローダー) を使います。これは、インポートのロード部分で起こることの近似です:

    module = None
    if spec.loader is not None and hasattr(spec.loader, 'create_module'):
        # It is assumed 'exec_module' will also be defined on the loader.
        module = spec.loader.create_module(spec)
    if module is None:
        module = ModuleType(spec.name)
    # The import-related module attributes get set here:
    _init_module_attrs(spec, module)

    if spec.loader is None:
        if spec.submodule_search_locations is not None:
            # namespace package
            sys.modules[spec.name] = module
        else:
            # unsupported
            raise ImportError
    elif not hasattr(spec.loader, 'exec_module'):
        module = spec.loader.load_module(spec.name)
        # Set __loader__ and __package__ if missing.
    else:
        sys.modules[spec.name] = module
        try:
            spec.loader.exec_module(module)
        except BaseException:
            try:
                del sys.modules[spec.name]
            except KeyError:
                pass
            raise
    return sys.modules[spec.name]

以下の詳細に注意してください:

> - `sys.modules` の中に与えられた名前を持つ既存のモジュールオブジェクトがあるなら、 import は既にそれを返しているでしょう。

> - モジュールは、ローダーがモジュールコードを実行する前に `sys.modules` に存在しています。 モジュールコードが (直接的または間接的に) 自分自身をインポートする可能性があるので、これは重要です; モジュールを `sys.modules` に追加することで、最悪のケースでは無限の再帰が、そして最良のケースでは複数回のロードが、前もって防止されます。

> - ロード処理に失敗した場合、その失敗したモジュールは -- そして、そのモジュールだけが -- `sys.modules` から取り除かれます。 `sys.modules` キャッシュに既に含まれていたすべてのモジュールと、副作用としてロードに成功したすべてのモジュールは、常にキャッシュに残されます。これはリロードとは対照的で、リロードの場合は失敗したモジュールも `sys.modules` に残されます。

> - 後のセクション で要約されるように、モジュールが作られてから実行されるまでの間にインポート機構はインポート関連のモジュール属性を設定します (上記擬似コード例の "_init_module_attrs")。

> - モジュール実行はモジュールの名前空間が構築されるロードの重要な瞬間です。実行はローダーに完全に委任され、ローダーは何をどのように構築するかを決定することになります。

> - ロードの間に作成されて exec_module() に渡されたモジュールは、インポートの終わりに返されるものとは異なるかもしれません 2。

バージョン 3.4 で変更: インポートシステムはローダーの定型的な責任を引き継ぎました。これらは以前は `importlib.abc.Loader.load_module()` メソッドによって実行されました。

### 5.4.1. ローダー

モジュールローダーは、ロードの重要な機能であるモジュール実行機能を提供します。インポート機構は、実行しようとするモジュールオブジェクトを単一の引数として `importlib.abc.Loader.exec_module()` メソッドを呼び出します。 `importlib.abc.Loader.exec_module()` から返された任意の値は無視されます。

ローダーは以下の仕様を満たしていなければいけません:

> - モジュールが (組み込みモジュールや動的に読み込まれる拡張モジュールではなくて) Python モジュールだった場合、ローダーはモジュールのグローバル名前空間 (`module.__dict__`) で、モジュールのコードを実行すべきです。

> - `exec_module()` の呼び出し中に `ImportError` 以外の例外が送出され、伝播されてきたとしても、モジュールをロードできない場合は `ImportError` を送出すべきです。

多くの場合、ファインダーとローダーは同じオブジェクトで構いません; そのような場合では `find_spec()` メソッドは単に `self` (訳注: オブジェクト自身) を返すだけです。

モジュールローダーは、 `create_module()` メソッドを実装することでロード中にモジュールオブジェクトを作成することを選択できます。このメソッドは、モジュール仕様を引数に取って、ロード中に使う新しいモジュールオブジェクトを返します。 `create_module()` はモジュールオブジェクトに属性を設定する必要はありません。もしこのメソッドが `None` を返すなら、インポート機構は新しいモジュールを自身で作成します。

バージョン 3.4 で追加: ローダーの `create_module()` メソッド。

バージョン 3.4 で変更: `load_module()` メソッドは `exec_module()` によって置き換えられ、インポート機構がロードのすべての定型責任を引き受けました。

既存のローダーとの互換性のため、もしローダーに `load_module()` メソッドが存在し、かつローダーが `exec_module()` を実装していなければ、インポート機構はローダーの `load_module()` メソッドを使います。しかし、 `load_module()` は deprecated であり、ローダーは代わりに `exec_module()` を実装すべきです。

`load_module()` メソッドは、モジュールを実行することに加えて上記で説明されたすべての定型的なロード機能を実施しなければなりません。同じ制約が適用されます。以下は追加の明確化です:

> - `sys.modules` に与えられた名前のモジュールが存在している場合、ローダーはその既存のモジュールを使わなければいけません。 (そうしないと `importlib.reload()` は正しく動かないでしょう。) 指定されたモジュールが `sys.modules` に存在しない場合、ローダーは新しいモジュールオブジェクトを作成し、 `sys.modules` に追加しなければいけません。

> - 無限の再帰または複数回のロードを防止するために、ローダーがモジュールコードを実行する前にモジュールは `sys.modules` に存在しなければなりません (must)。

> - ロード処理に失敗した場合、ローダーは `sys.modules` に追加したモジュールを取り除かなければいけませんが、それはロードに失敗したモジュール のみ を、そのモジュールがローダー自身に明示的にロードされた場合に限り、除去しなければなりません。

バージョン 3.5 で変更: `exec_module()` が定義されていて `create_module()` が定義されていない場合、 `DeprecationWarning` が送出されるようになりました。

バージョン 3.6 で変更: `exec_module()` が定義されていて `create_module()` が定義されていない場合、 `ImportError` が送出されるようになりました。

### 5.4.2. サブモジュール

サブモジュールをロードするのにどのようなメカニズム (例えば、 `importlib` API 、 `import` または `import-from` ステートメント、またはビルトイン関数の `__import__`) が使われた場合でも、バインディングはサブモジュールオブジェクトを親モジュールの名前空間に配置します。例えば、もしパッケージ `spam` がサブモジュール `foo` を持っていた場合、 `spam.foo` をインポートした後は `spam` は値がサブモジュールに束縛された属性 `foo` を持ちます。以下のディレクトリ構造を持っているとしましょう:

    spam/
        __init__.py
        foo.py
        bar.py

そして `spam/__init__.py` は以下のようになっているとします:

    from .foo import Foo
    from .bar import Bar

このとき、以下を実行することにより `spam` モジュールの中に `foo` と `bar` に束縛された名前が置かれます:

    >>> import spam
    >>> spam.foo
    <module 'spam.foo' from '/tmp/imports/spam/foo.py'>
    >>> spam.bar
    <module 'spam.bar' from '/tmp/imports/spam/bar.py'>

Python の慣れ親しんだ名前束縛ルールからするとこれは驚きかもしれませんが、それは実際インポートシステムの基本的な機能です。不変に保たなければならないのは (上記のインポートの後などで) `sys.modules['spam']` と `sys.modules['spam.foo']` が存在する場合、後者が前者の `foo` 属性として存在しなければならないということです。

### 5.4.3. モジュール仕様

インポート機構は、インポートの間 (特にロードの前) に、個々のモジュールについてのさまざまな情報を扱います。情報のほとんどはすべてのモジュールで共通です。モジュール仕様の目的は、このインポート関連の情報をモジュールの単位でカプセル化することです。

インポートの際にモジュール仕様を使うことは、インポートシステムコンポーネント間、例えばモジュール仕様を作成するファインダーとそれを実行するローダーの間で状態を転送することを可能にします。最も重要なのは、それによってインポート機構がロードの定型的な作業を実行できるようになるということです。これに対して、モジュール仕様なしではローダがその責任を担っていました。

モジュール仕様は、モジュールオブジェクトの `__spec__` 属性として公開されます。 モジュール仕様の内容の詳細については `ModuleSpec` を参照してください。

バージョン 3.4 で追加.

### 5.4.4. インポート関連のモジュール属性

インポート機構はロードの間、モジュールの仕様に基づいて、ローダーがモジュールが実行する前に以下の属性を書き込みます。

`__name__`

  `__name__` 属性はモジュールの完全修飾名に設定されなければなりません。この名前を利用してインポートシステムでモジュールを一意に識別します。

`__loader__`

  `__loader__` 属性はモジュールロード時にインポート機構が使用したローダーオブジェクトに設定されなければなりません。この属性は普通は内省用のものですが、ローダー固有の追加機能のために用いることが出来ます。例えばローダー関連のデータの取得です。

`__package__`

  モジュールの `__package__` 属性は設定されなければなりません。値は文字列でなければなりませんが、`__name__` と同じ値でも構いません。モジュールがパッケージの場合、`__package__` の値はその `__name__` でなければなりません。モジュールがパッケージでない場合、トップレベルのモジュールでは `__package__` 空の文字列、サブモジュールでは親のパッケージ名でなければなりません。詳細は PEP 366 を参照してください。

  この属性は PEP 366 で定義されているように、メインモジュールからの明示的な相対インポートを計算するために、 `__name__` の代わりに使用されます。 この属性は `__spec__.parent` と同じ値を持つことを要求されます。

  バージョン 3.6 で変更: `__package__` の値が `__spec__.parent` と同じ値を持つことを要求されるようになりました。

`__spec__`

  `__spec__` 属性はモジュールロード時に使用されたモジュールスペックに設定されなければなりません。 `__spec__` を適切に設定すると インタープリタ起動中に初期化されるモジュール にも同様に適用されます。 例外は `__main__` で、`__spec__` は 場合によっては None に設定されます。

  `__package__` が定義されていないときは `__spec__.parent` がフォールバックとして使われます。

  バージョン 3.4 で追加.

  バージョン 3.6 で変更: `__package__` が定義されていないときに `__spec__.parent` がフォールバックとして使われるようになりました。

`__path__`

  モジュールが (通常のまたは名前空間) パッケージの場合、モジュールオブジェクトの `__path__` 属性が設定される必要があります。値はイテレート可能でなければなりませんが、`__path__` に意味がない場合は空でも構いません。`__path__` が空でない場合、イテレート時に文字列を生成しなければなりません。`__path__` のセマンティクスの詳細は 下記 の通りです。

  パッケージでないモジュールは `__path__` 属性を持ってはいけません。

`__file__`

`__cached__`

  `__file__` はオプションです。もし設定されるならば、この属性の値は文字列でなければなりません。もしそのような属性が意味を持たない場合 (例えばモジュールがデータベースからロードされた場合) インポートシステムは `__file__` を未設定のままにしても構いません。

  もし `__file__` を設定するなら、 `__cached__` 属性もコードのコンパイルされたバージョンのどれか (例えば、バイトコンパイルされたファイル) へのパスに設定することが適切でしょう。この属性を設定するにあたってファイルが存在する必要はありません; パスは、単にコンパイルされたファイルが存在するかもしれない場所を示しているだけです ( PEP 3147 を参照)。

  `__file__` が設定されない場合にも `__cached__` を設定することは適切です。しかし、そのシナリオはかなり変則的です。究極的には、ローダーとは `__file__` と `__cached__` のどちらかまたは両方を利用するものです。したがって、もしローダーがキャッシュされたモジュールからロードする一方でファイルからはロードしないなら、その変則的なシナリオは適切でしょう。

### 5.4.5. module.__path__

定義より、モジュールに `__path__` 属性があれば、そのモジュールはパッケージとなります。

パッケージの `__path__` 属性は、そのサブパッケージのインポート中に使われます。インポート機構の内部では、それは `sys.path` とほとんど同じように機能します。つまり、インポート中にモジュールを探す場所のリストを提供します。しかし、一般的に `__path__` は `sys.path` よりも制約が強いです。

`__path__` は文字列の iterable でなければいけませんが、空でも構いません。 `sys.path` と同じ規則がパッケージの `__path__` にも適用され、パッケージの `__path__` を走査するときに (後で解説する) `sys.path_hooks` が考慮に入れられます。

パッケージの `__init__.py` ファイルは、パッケージの `__path__` 属性を設定もしくは変更することがあり、これが PEP 420 以前の名前空間パッケージの典型的な実装方法でした。 PEP 420 の採択により、もはや名前空間パッケージは、 `__path__` を操作するコードだけを含む `__init__.py` ファイルを提供する必要がなくなりました;インポート機構は、名前空間パッケージに対し自動的に適切な `__path__` をセットします。

### 5.4.6. モジュールの repr

デフォルトでは、すべてのモジュールは利用可能な repr を持っています。ただしこれは上位で設定された属性に依存しており、モジュール仕様によってモジュールオブジェクトの repr をより明示的に制御することができます。

もしモジュールが仕様 (`__spec__`) を持っていれば、インポート機構はそこから repr を生成しようとします。もしそれが失敗するか、または仕様が存在しなければ、インポートシステムはモジュールで入手可能なあらゆる情報を使ってデフォルトの repr を構築します。それは `module.__name__`, `module.__file__`, `module.__loader__` を (足りない情報についてはデフォルト値を使って補いながら) repr への入力として使おうと試みます。

これが使われている正確な規則です:

> - モジュールが `__spec__` 属性を持っていれば、仕様に含まれる情報が repr を生成するために使われます。 "name", "loader", "origin", "has_location" 属性が参照されます。

> - モジュールに `__file__` 属性がある場合は、モジュールの repr の一部として使われます。

> - モジュールに `__file__` はないが `__loader__` があり、その値が `None` ではない場合は、ローダーの repr がモジュールの repr の一部として使われます。

> - そうでなければ、単にモジュールの `__name__` を repr の中で使います。

バージョン 3.4 で変更: `loader.module_repr()` の使用は deprecated です。インポート機構によりモジュール仕様がモジュール repr を生成するために使用されるようになりました。

Python 3.3 との後方互換性のために、ローダーの `module_repr()` メソッドが定義されていたら、モジュール repr を生成するために上記のいずれかのアプローチを試す前にそのメソッドが呼ばれます。ただし、このメソッドは deprecated です。

## 5.5. パスベース・ファインダー

上で触れた通り、 Python にはいくつかのデフォルトのメタパス・ファインダーが備わっています。そのうちの 1 つは パスベース・ファインダー (`PathFinder`) と呼ばれ、 パスエントリ のリストである インポートパス を検索します。それぞれのパスエントリは、モジュールを探す場所を指しています。

パスベース・ファインダー自体は何かのインポート方法を知っているわけではありません。その代わりに、個々のパスエントリを走査し、それぞれに特定の種類のパスの扱いを知っているパスエントリ・ファインダーを関連付けます。

デフォルトのパスエントリ・ファインダーは、ファイルシステム上のモジュールを見つけるためのすべてのセマンティクスを実装しています。それは Python ソースコード (`.py` ファイル) 、Python バイトコード (`.pyc` ファイル) 、共有ライブラリ (例えば `.so` ファイル) などの特別なファイルタイプを処理します。標準ライブラリの `zipimport` モジュールによってサポートされる場合は、デフォルトのパスエントリ・ファインダーは (共有ライブラリ以外の) すべてのファイルタイプの zip ファイルからのロードも扱います。

パスエントリはファイルシステム上の場所に限定される必要はありません。URL やデータベースクエリやその他文字列で指定できる場所を参照することも可能です。

パスベース・ファインダーにはフックやプロトコルを追加することができ、それによって検索可能なパスエントリの種類を拡張し、カスタマイズすることができます。例えば、ネットワーク上の URL をパスエントリとしてサポートしたい場合、 web 上のモジュールを見つけるために HTTP の取り扱い方を実装したフックを書くことができます。この (呼び出し可能オブジェクトである) フックは、下で解説するプロトコルをサポートする パスエントリ・ファインダー を返します。このプロトコルは web からモジュールのローダーを取得するのに使われます。

警告の言葉: この節と前の節の両方で ファインダー という言葉が、 メタパス・ファインダー と パスエントリ・ファインダー という用語で区別されて使われています。これら 2 種類のファインダーは非常に似ており、似たプロトコルをサポートし、インポート処理で同じように機能しますが、微妙に異なっているのを心に留めておくのは重要です。特に、メタパス・ファインダーはインポート処理の開始時、 `sys.meta_path` の走査が動くときに動作します。

それとは対照的に、パスエントリ・ファインダーはある意味でパスベース・ファインダーの実装詳細であり、実際 `sys.meta_path` からパスベース・ファインダーが取り除かれた場合、パスエントリ・ファインダーの実装は何も実行されないでしょう。

### 5.5.1. パスエントリ・ファインダー

パスベース・ファインダー には、文字列 パスエントリ で指定された場所の Python モジュールや Python パッケージを見つけ、ロードする責任があります。ほとんどのパスエントリはファイルシステム上の場所を指定していますが、そこに制限される必要はありません。

メタパス・ファインダーとして、 パスベース・ファインダー には前に解説した `find_spec()` プロトコルが実装されていますが、これに加えて インポートパス からモジュールを見つけ、ロードする方法をカスタマイズするために使えるフックを提供しています。

パスベース・ファインダー は `sys.path` 、 `sys.path_hooks` 、 `sys.path_importer_cache` という 3 つの変数を使います。さらにパッケージオブジェクトの `__path__` 属性も使います。これらによって、インポート処理をカスタマイズする方法が提供されます。

`sys.path` には、モジュールとパッケージを探す場所文字列の一覧があります。これは `PYTHONPATH` 環境変数とその他様々なインストール方法や実装に依存するデフォルト値で初期化されます。 `sys.path` 内の要素は、ファイルシステム上のディレクトリや zip ファイルやその他モジュールを探すべき "場所" となりうるもの (`site` モジュールを参照) を指すことができます。文字列およびバイト列のみを `sys.path` に入れるべきです; 他のデータ型は無視されます。バイト列の要素のエンコーディングは、各 パスエントリ・ファインダー によって判別されます。

パスベース・ファインダー は メタパス・ファインダー なので、インポート機構は、前で解説したパスベース・ファインダーの `find_spec()` メソッドを呼び出すことで インポートパス の検索を始めます。 `path` 引数が `find_spec()` に渡されたときは、それは走査するパス文字列のリスト - 典型的にはそのパッケージの中でインポートしているパッケージの `__path__` 属性になります。 `path` 引数が `None` だった場合、それは最上位のインポートであることを示していて、 `sys.path` が使われます。

パスベース・ファインダーは検索パスのすべての要素について反復処理をし、それぞれのパスに対して適切な パスエントリ・ファインダー (`PathEntryFinder`) を探します。これは時間のかかる処理 (例えば、この検索のための stat() 呼び出しのオーバーヘッド) になり得るので、パスベース・ファインダーはパス要素からパスエントリ・ファインダーへの対応付けをキャッシュとして持っておきます。このキャッシュは `sys.path_importer_cache` に持っています (名前に反して、このキャッシュは実際には インポーター には制限されておらず、ファインダーオブジェクトを保持します) 。このようにして、時間のかかる特定の パスエントリ の場所のための パスエントリ・ファインダー の検索を一度だけ検索すれば良くなります。パスベース・ファインダーにパスエントリの検索を再度行わせるために、ユーザコードでは自由に `sys.path_importer_cache` からキャッシュを取り除いて構いません 3 。

path entry がキャッシュの中に無かった場合、 path based finder は `sys.path_hooks` の中の呼び出し可能オブジェクトを全て辿ります。 このリストのそれぞれの path entry フック は、検索する path entry という引数 1 つを渡して呼び出されます。 その呼び出し可能オブジェクトは path entry を扱える path entry finder を返すか、 `ImportError` を送出します。 `ImportError` は、フックが path entry のための path entry finder を探せないことを報せるために path based finder が使います。 この例外は処理されず、 import path を辿っていく処理が続けられます。 フックは引数として文字列またはバイト列オブジェクトを期待します; バイト列オブジェクトのエンコーディングはフックに任されていて (例えば、ファイルシステムのエンコーディングの UTF-8 やそれ以外などです) 、フックが引数をデコードできなかった場合は `ImportError` を送出すべきです。

`sys.path_hooks` を辿る処理が パスエントリ・ファインダー を何も返さずに終わった場合、パスベース・ファインダーの `find_spec()` メソッドは、 `sys.path_importer_cache` に (このパスエントリに対するファインダーが存在しないことを示すために) `None` を保存し、 メタパス・ファインダー はモジュールが見つからなかったことを伝えるために `None` を返します。

`sys.path_hooks` 上の パスエントリフック 呼び出し可能オブジェクトの戻り値のいずれかが パスエントリ・ファインダー であった 場合、後で出てくるモジュール仕様を探すためのプロトコルが使われ、それがモジュールをロードするために使われます。

（空の文字列によって表される）現在のディレクトリは、 `sys.path` の他のエントリとは多少異なる方法で処理されます。まず、現在のディレクトリが存在しないことが判明した場合、 `sys.path_importer_cache` には何も追加されません。次に、現在のディレクトリに対する値は個々のモジュールのルックアップで毎回新たに検索されます。 3番目に、 `sys.path_importer_cache` に使われ、 `importlib.machinery.PathFinder.find_spec()` が返すパスは、実際のディレクトリであって空の文字列ではありません。

### 5.5.2. パスエントリ・ファインダー・プロトコル

モジュールと初期化されたパッケージのインポートをサポートするため、および名前空間パッケージのポーションとして提供するために、パスエントリ・ファインダーは `find_spec()` メソッドを実装しなければいけません。

`find_spec()` は 2 つの引数を取ります。インポートしようとしているモジュールの完全修飾名と、 (オプションの) 対象モジュールです。 find_spec() はモジュールに対応する完全に初期化 (populated) された仕様を返します。この仕様は (1つの例外を除いて) 常に "loader" セットを持っています。

モジュール仕様が名前空間 ポーション を表していることをインポート機構に示すために、パスエントリ・ファインダーはモジュール仕様の "loader" を `None` に、 "submodule_search_locations" を名前空間ポーションを含むリストに設定します。

バージョン 3.4 で変更: `find_spec()` は `find_loader()` と `find_module()` を置き換えました。両者は deprecated ですが、 find_spec() が定義されていなければ使われます。

古いパスエントリ・ファインダーの中には、 `find_spec()` の代わりにこれら 2 つの deperecated なメソッドのうちのいずれかを実装しているものがあるかもしれません。これらのメソッドは後方互換性のためにまだ考慮されています。しかし、パスエントリ・ファインダーに `find_spec()` が実装されていれば、古いメソッドは無視されます。

`find_loader()` はインポートされるモジュールの完全修飾名を引数に取ります。 `find_loader()` は、第 1 要素がローダで第 2要素が名前空間 ポーション である 2 要素のタプルを返します。第 1 要素 (つまりローダー) が `None` の場合、その意味は、パスエントリ・ファインダー自身は指定されたモジュールのためのローダーを持っていないものの、パスエントリがモジュールの名前空間ポーションに関係している (contribute) のをパスエントリ・ファインダーが知っているということです。これは、ほとんど常にファイルシステム上に物理的な実体のない名前空間パッケージをインポートしようとした場合です。パスエントリ・ファインダーがローダーとして `None` を返す場合には、 2 要素タプルである戻り値の第 2 要素はシーケンスでなければなりません。ただし、シーケンスは空でも構いません。

`find_loader()` が `None` でないローダー値を返した場合、ポーションは無視され、パスベース・ファインダーからローダーが返され、パスエントリ上の検索が終了します。

他のインポート機構の実装に対する後方互換性のために、多くのパスエントリ・ファインダーは、メタパス・ファインダーがサポートするのと同じ伝統的な `find_module()` メソッドもサポートしています。しかし、パスエントリ・ファインダーの `find_module()` メソッドは、決して `path` 引数では呼び出されません (このメソッドは、パスフックの最初の呼び出しから適切なパス情報を記録する動作が期待されています)。

パスエントリ・ファインダーの `find_module()` メソッドは deprecated です。なぜなら、その方法ではパスエントリ・ファインダーが名前空間パッケージに対してポーションを提供することができないからです。もし `find_loader()` と `find_module()` の両方がパスエントリ・ファインダーに存在したら、インポートシステムは常に `find_module()` よりも `find_loader()` を優先して呼び出します。

## 5.6. 標準のインポートシステムを置き換える

インポートシステム全体を置き換えるための最も信頼性のある仕組みは、 `sys.meta_path` のデフォルトの内容を削除し、全部をカスタムのメタパスフックで置き換えるものです。

もし、 import 文の動作だけを変更し、インポートシステムにアクセスする他の API には影響を与えなくてもよければ、組み込みの `__import__()` 関数を置き換えるだけで十分です。この手法は、ある 1 つのモジュール内だけで import 文の動作を変更するのにも用いられます。

(標準のインポートシステム全体を停止するのではなく) すでにメタパスにいるフックからあるモジュールのインポートを選択的に防ぐためには、 `find_spec()` から `None` を返す代わりに、直接 `ModuleNotFoundError` を送出するだけで十分です。 `None` を返すのはメタパスの走査を続けるべきであることを意味しますが、例外を送出するとすぐに走査を打ち切ります。

## 5.7. __main__ に対する特別な考慮

`__main__` モジュールは、 Python のインポートシステムに関連する特別なケースです。 他の場所 で言及されているように、 `__main__` モジュールは `sys` や `builtins` などと同様にインタプリタースタートアップで直接初期化されます。しかし、前者 2 つのモジュールと違って、 `__main__` は厳密にはビルトインのモジュールとしての資格を持っていません。これは、 `__main__` が初期化される方法がインタプリタが起動されるときのフラグやその他のオプションに依存するためです。

### 5.7.1. __main__.__spec__

`__main__` がどのように初期化されるかに依存して、 `__main__.__spec__` は適切に設定されることもあれば `None` になることもあります。

Python が `-m` オプションを付けて実行された場合には、 `__spec__` は対応するモジュールまたはパッケージのモジュール仕様に設定されます。また、ディレクトリや zip ファイル、または他の `sys.path` エントリを実行する処理の一部として `__main__` モジュールがロードされる場合にも `__spec__` が生成 (populate) されます。

それ以外のケース では、 `__main__.__spec__` は `None` に設定されます。これは、 `__main__` を生成 (populate) するために使われたコードがインポート可能なモジュールと直接一致していないためです:

- 対話プロンプト

- `-c` オプション

- stdin から起動された場合

- ソースファイルやバイトコードファイルから直接起動された場合

最後のケースでは、たとえ技術的にはファイルがモジュールとして直接インポートできた としても `__main__.__spec__` は常に `None` になることに注意してください。もし `__main__` において有効なモジュールメタデータが必要なら `-m` スイッチを使ってください。

`__main__` がインポート可能なモジュールと一致し、 `__main__.__spec__` がそれに応じて設定されていたとしても、それでもなお、この 2 つのモジュールは別物とみなされることに注意してください。これは、 `if __name__ == "__main__":` チェックによって保証されるブロックは、 `__main__` 名前空間を生成 (populate) するためにモジュールが使用される時にだけ実行され、通常のインポート時には実行されない、という事実に起因しています。

## 5.8. 取り掛かり中の問題

XXX 図があるととても良い。

XXX * (import_machinery.rst) モジュールとパッケージの属性のみに紙面を割いた節を設けるのは何如でしょうか? もしかしたらデータモデルについての言語リファレンスのページにある関係する内容を拡張したり、置き換えるようなものになるかもしれません。

XXX ライブラリマニュアルの runpy や pkgutil の解説の先頭すべてに、"こちらも参照 (See Also)" という、この新しいインポートシステムの節へのリンクを置くべき。

XXX `__main__` が初期化される様々な方法についてより多くの説明を追加する?

XXX `__main__` の特異性/落とし穴についてより多くの情報を追加する (つまり PEP 395 からコピーする)

## 5.9. 参考資料

Python の初期の頃からすると、インポート機構は目覚ましい発展を遂げました。 一部細かいところがドキュメントが書かれたときから変わってはいますが、最初期の パッケージの仕様 はまだ読むことができます。

オリジナルの `sys.meta_path` の仕様は PEP 302 で、その後継となる拡張が PEP 420 です。

PEP 420 は Python 3.3 に 名前空間パッケージ を導入しています。 PEP 420 はまた `find_module()` に代わるものとして `find_loader()` プロトコルを導入しています。

PEP 366 は、メインモジュールでの明示的な相対インポートのために追加した `__package__` 属性の解説をしています。

PEP 328 は絶対インポート、明示的な相対インポート、および、当初 `__name__` で提案し、後に PEP 366 が `__package__` で定めた仕様を導入しました。

PEP 338 はモジュールをスクリプトとして実行するときの仕様を定めています。

PEP 451 は、モジュール仕様オブジェクトにおけるモジュール毎のインポート状態のカプセル化を追加しています。また、ローダーの定型的な責任のほとんどをインポート機構に肩代わりさせています。これらの変更により、インポートシステムのいくつかの API が deprecate され、またファインダーとローダーには新しいメソッドが追加されました。

脚注

1

  `types.ModuleType` を参照してください。

2

  importlib の実装は、戻り値を直接使うことは避けています。その代わりに、モジュール名を調べて `sys.modules` からモジュールオブジェクトを得ます。こうすることの間接的な効果は、インポートされたモジュールが `sys.modules` にいる自分自身を置き換えることがあるということです。これは実装依存の動作であり、他の Python 実装では保証されていない動作です。

3

  レガシーなコードでは、 `sys.path_importer_cache` に `imp.NullImporter` のインスタンスがいることがあります。それの代わりに `None` を使うようにコードを変更することが推奨されます。より詳しいことは Python コードの移植 を参照してください。