# `importlib` --- `import` の実装

バージョン 3.1 で追加.

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

## はじめに

`importlib` パッケージの目的は3つあります。

1つ目は Python ソースコード中にある `import` 文の(そして、拡張として、 `__import__()` 関数の)実装を提供することです。このパッケージは `import` 文の、どの Python インタープリターでも動作する実装を提供します。また、 Python 以外の言語で実装されたどの実装よりも把握しやすい実装を提供します。

2つ目の目的は、このパッケージが公開している `import` を実装するための要素を利用して、(インポーター として知られる) インポートプロセスで動作するカスタムのオブジェクトを実装しやすくすることです。

Three, the package contains modules exposing additional functionality for managing aspects of Python packages:

- `importlib.metadata` presents access to metadata from third-party distributions.

- `importlib.resources` provides routines for accessing non-code "resources" from Python packages.

参考

import 文

  `import` 文の言語リファレンス。

Packages specification

  パッケージの元の仕様。幾つかの動作はこの仕様が書かれた頃から変更されています (例: `sys.modules` で `None` に基づくリダイレクト)。

`__import__()` 関数

  `import` 文はこの関数のシンタックスシュガーです。

sys.path モジュール検索パスの初期化

  The initialization of `sys.path`.

PEP 235

  大文字小文字を区別しないプラットフォームでのインポート

PEP 263

  Python のソースコードのエンコーディング

PEP 302

  新しいインポートフック

PEP 328

  複数行のインポートと、絶対/相対インポート

PEP 366

  main モジュールの明示的な相対インポート

PEP 420

  暗黙的な名前空間パッケージ

PEP 451

  インポートシステムのための ModuleSpec 型

PEP 488

  PYO ファイルの撤廃

PEP 489

  複数フェーズでの拡張モジュールの初期化

PEP 552

  決定論的 pyc

PEP 3120

  デフォルトのソースエンコーディングとして UTF-8 を使用

PEP 3147

  PYC リポジトリディレクトリ

## 関数

importlib.__import__(name, globals=None, locals=None, fromlist=(), level=0)

  組み込みの `__import__()` 関数の実装です。

  注釈

  プログラムからモジュールをインポートする場合はこの関数の代わりに `import_module()` を使ってください。

importlib.import_module(name, package=None)

  モジュールをインポートします。name 引数は、インポートするモジュールを絶対または相対表現 (例えば `pkg.mod` または `..mod`) で指定します。name が相対表現で与えられたら、package 引数を、パッケージ名を解決するためのアンカーとなるパッケージの名前に設定する必要があります (例えば `import_module('..mod', 'pkg.subpkg')` は `pkg.mod` をインポートします)。

  `import_module()` 関数は `importlib.__import__()` を単純化するラッパーとして働きます。つまり、この関数のすべての意味は `importlib.__import__()` から受け継いでいます。これらの2つの関数の最も重要な違いは、 `import_module()` が指定されたパッケージやモジュール (例えば `pkg.mod`) を返すのに対し、 `__import__()` はトップレベルのパッケージやモジュール (例えば `pkg`) を返すことです。

  もしモジュールを動的にインポートしていて、インタープリタの実行開始後にモジュールが作成された (例えば、 Python ソースファイルを作成した) 場合、インポートシステムが新しいモジュールを見つけられるように、 `invalidate_caches()` を呼ぶ必要があるでしょう。

  バージョン 3.3 で変更: 親パッケージは自動的にインポートされます。

importlib.find_loader(name, path=None)

  Find the loader for a module, optionally within the specified path. If the module is in `sys.modules`, then `sys.modules[name].__loader__` is returned (unless the loader would be `None` or is not set, in which case `ValueError` is raised). Otherwise a search using `sys.meta_path` is done. `None` is returned if no loader is found.

  A dotted name does not have its parents implicitly imported as that requires loading them and that may not be desired. To properly import a submodule you will need to import all parent packages of the submodule and use the correct argument to path.

  バージョン 3.3 で追加.

  バージョン 3.4 で変更: If `__loader__` is not set, raise `ValueError`, just like when the attribute is set to `None`.

  バージョン 3.4 で非推奨: Use `importlib.util.find_spec()` instead.

importlib.invalidate_caches()

  `sys.meta_path` に保存されたファインダーの内部キャッシュを無効にします。ファインダーが `invalidate_caches()` を実装していれば、無効化を行うためにそれが呼び出されます。すべてのファインダーが新しいモジュールの存在に気づくことを保証しているプログラムの実行中に、モジュールが作成またはインストールされたなら、この関数が呼び出されるべきです。

  バージョン 3.3 で追加.

  バージョン 3.10 で変更: Namespace packages created/installed in a different `sys.path` location after the same namespace was already imported are noticed.

importlib.reload(module)

  以前にインポートされた module をリロードします。引数はモジュールオブジェクトでなければならず、したがってそれ以前に必ずインポートに成功していなければなりません。この関数は、モジュールのソースファイルを外部エディタで編集していて Python インタープリタから離れることなく新しいバージョンを試したい際に便利です。戻り値はモジュールオブジェクトです。 (もし再インポートが異なるオブジェクトを `sys.modules` に配置したら、元の module とは異なるかもしれません。)

  `reload()` が実行された場合:

  - Python モジュールのコードは再コンパイルされ、モジュールレベルのコードが再度実行されます。モジュールの辞書中にある何らかの名前に結び付けられたオブジェクトは、そのモジュールを最初にロードしたときの ローダー を再利用して新たに定義されます。拡張モジュールの `init` 関数が二度呼び出されることはありません。

  - Python における他のオブジェクトと同様、以前のオブジェクトのメモリ領域は、参照カウントがゼロにならないかぎり再利用されません。

  - モジュール名前空間内の名前は新しいオブジェクト (または更新されたオブジェクト) を指すよう更新されます。

  - 以前のオブジェクトが (外部の他のモジュールなどからの) 参照を受けている場合、それらを新たなオブジェクトに再束縛し直すことはないので、必要なら自分で名前空間を更新しなければなりません。

  いくつか補足説明があります:

  モジュールが再ロードされた際、その辞書 (モジュールのグローバル変数を含みます) はそのまま残ります。名前の再定義を行うと、以前の定義を上書きするので、一般的には問題はありません。新たなバージョンのモジュールが古いバージョンで定義された名前を定義していない場合、古い定義がそのまま残ります。辞書がグローバルテーブルやオブジェクトのキャッシュを維持していれば、この機能をモジュールを有効性を引き出すために使うことができます --- つまり、 `try` 文を使えば、必要に応じてテーブルがあるかどうかをテストし、その初期化を飛ばすことができます:

      try:
          cache
      except NameError:
          cache = {}

  組み込みモジュールや動的にロードされるモジュールを再ロードすることは、一般的にそれほど便利ではありません。 `sys`, `__main__`, `builtins` やその他重要なモジュールの再ロードはお勧め出来ません。多くの場合、拡張モジュールは 1 度以上初期化されるようには設計されておらず、再ロードされた場合には何らかの理由で失敗するかもしれません。

  一方のモジュールが `from` ... `import` ... を使って、オブジェクトを他方のモジュールからインポートしているなら、他方のモジュールを `reload()` で呼び出しても、そのモジュールからインポートされたオブジェクトを再定義することはできません --- この問題を回避する一つの方法は、 `from` 文を再度実行することで、もう一つの方法は `from` 文の代わりに `import` と限定的な名前 (module.name) を使うことです。

  あるモジュールがクラスのインスタンスを生成している場合、そのクラスを定義しているモジュールの再ロードはそれらインスタンスのメソッド定義に影響しません --- それらは古いクラス定義を使い続けます。これは派生クラスの場合でも同じです。

  バージョン 3.4 で追加.

  バージョン 3.7 で変更: リロードされたモジュールの `ModuleSpec` が欠けていたときは `ModuleNotFoundError` が送出されます。

## `importlib.abc` -- インポートに関連する抽象基底クラス

ソースコード: Lib/importlib/abc.py

`importlib.abc` モジュールは、 `import` に使われるすべてのコア抽象基底クラス含みます。コア抽象基底クラスの実装を助けるために、コア抽象基底クラスのサブクラスもいくつか提供されています。

抽象基底クラス階層:

    object
     +-- Finder (deprecated)
     +-- MetaPathFinder
     +-- PathEntryFinder
     +-- Loader
          +-- ResourceLoader --------+
          +-- InspectLoader          |
               +-- ExecutionLoader --+
                                     +-- FileLoader
                                     +-- SourceLoader

class importlib.abc.Finder

  An abstract base class representing a finder.

  バージョン 3.3 で非推奨: Use `MetaPathFinder` or `PathEntryFinder` instead.

  abstractmethod find_module(fullname, path=None)

    An abstract method for finding a loader for the specified module. Originally specified in PEP 302, this method was meant for use in `sys.meta_path` and in the path-based import subsystem.

    バージョン 3.4 で変更: Returns `None` when called instead of raising `NotImplementedError`.

    バージョン 3.10 で非推奨: Implement `MetaPathFinder.find_spec()` or `PathEntryFinder.find_spec()` instead.

class importlib.abc.MetaPathFinder

  meta path finder を表す抽象基底クラスです。

  バージョン 3.3 で追加.

  バージョン 3.10 で変更: No longer a subclass of `Finder`.

  find_spec(fullname, path, target=None)

    指定されたモジュールに対応する スペック を検索する抽象メソッド。もしこれがトップレベルのインポートなら、 path は `None` です。そうでなければ、これはサブパッケージまたはモジュールのための検索で、 path は親パッケージの `__path__` の値です。スペックが見つからなければ `None` が返されます。 `target` は、渡されてきたならモジュールオブジェクトです。これはファインダーがどのようなスペックを返せばよいか推測するために使用します。具体的な `MetaPathFinders` を実装するためには `importlib.util.spec_from_loader()` が便利かもしれません。

    バージョン 3.4 で追加.

  find_module(fullname, path)

    A legacy method for finding a loader for the specified module. If this is a top-level import, path will be `None`. Otherwise, this is a search for a subpackage or module and path will be the value of `__path__` from the parent package. If a loader cannot be found, `None` is returned.

    If `find_spec()` is defined, backwards-compatible functionality is provided.

    バージョン 3.4 で変更: Returns `None` when called instead of raising `NotImplementedError`. Can use `find_spec()` to provide functionality.

    バージョン 3.4 で非推奨: Use `find_spec()` instead.

  invalidate_caches()

    このファインダーで使われている内部キャッシュがあれば無効にするオプションのメソッドです。 `sys.meta_path` 上のすべてのファインダーのキャッシュを無効化する際、 `importlib.invalidate_caches()` によって使われます。

    バージョン 3.4 で変更: Returns `None` when called instead of `NotImplemented`.

class importlib.abc.PathEntryFinder

  path entry finder を表す抽象基底クラスです。 `MetaPathFinder` と似ているところがありますが、 `PathEntryFinder` は `importlib.machinery.PathFinder` が提供するパスに基づく import サブシステムの中でのみ使うことが意図されています。

  バージョン 3.3 で追加.

  バージョン 3.10 で変更: No longer a subclass of `Finder`.

  find_spec(fullname, target=None)

    指定されたモジュールに対応する スペック を検索する抽象メソッド。ファインダーは、割り当てられている パス・エントリー 内のモジュールだけを検索します。スペックが見つからなければ `None` が返されます。 `target` は、渡されてきたならモジュールオブジェクトです。これはファインダーがどのようなスペックを返せばよいか推測するために使用します。具体的な `PathEntryFinders` を実装するためには `importlib.util.spec_from_loader()` が便利かもしれません。

    バージョン 3.4 で追加.

  find_loader(fullname)

    A legacy method for finding a loader for the specified module. Returns a 2-tuple of `(loader, portion)` where `portion` is a sequence of file system locations contributing to part of a namespace package. The loader may be `None` while specifying `portion` to signify the contribution of the file system locations to a namespace package. An empty list can be used for `portion` to signify the loader is not part of a namespace package. If `loader` is `None` and `portion` is the empty list then no loader or location for a namespace package were found (i.e. failure to find anything for the module).

    If `find_spec()` is defined then backwards-compatible functionality is provided.

    バージョン 3.4 で変更: Returns `(None, [])` instead of raising `NotImplementedError`. Uses `find_spec()` when available to provide functionality.

    バージョン 3.4 で非推奨: Use `find_spec()` instead.

  find_module(fullname)

    A concrete implementation of `Finder.find_module()` which is equivalent to `self.find_loader(fullname)[0]`.

    バージョン 3.4 で非推奨: Use `find_spec()` instead.

  invalidate_caches()

    このファインダーで使われている内部キャッシュがあれば無効にするオプションのメソッドです。キャッシュされたすべてのファインダーの無効化する際、 `importlib.machinery.PathFinder.invalidate_caches()` によって使われます。

class importlib.abc.Loader

  loader の抽象基底クラスです。ローダーの厳密な定義は PEP 302 を参照してください。

  リソースの読み出しをサポートさせたいローダーには、 `importlib.resources.abc.ResourceReader` で指定されている `get_resource_reader()` メソッドを実装してください。

  バージョン 3.7 で変更: オプションの `get_resource_reader()` メソッドが導入されました。

  create_module(spec)

    モジュールをインポートする際に使用されるモジュールオブジェクトを返すメソッド。このメソッドは `None` を戻すことができ、その場合はデフォルトのモジュール作成のセマンティクスが適用されることを示します。

    バージョン 3.4 で追加.

    バージョン 3.6 で変更: `exec_module()` が定義されている場合は、このメソッドはオプションではなくなりました。

  exec_module(module)

    モジュールがインポートまたはリロードされる際に、そのモジュールをモジュール自身の名前空間の中で実行する抽象的なメソッド。 `exec_module()` が呼ばれる時点で、モジュールはすでに初期設定されている必要があります。 このメソッドが存在するときは、 `create_module()` の定義が必須です。

    バージョン 3.4 で追加.

    バージョン 3.6 で変更: `create_module()` の定義が必須となりました。

  load_module(fullname)

    モジュールをロードするためのレガシーなメソッドです。モジュールがロードできなければ `ImportError` を送出し、ロードできればロードされたモジュールを返します。

    If the requested module already exists in `sys.modules`, that module should be used and reloaded. Otherwise the loader should create a new module and insert it into `sys.modules` before any loading begins, to prevent recursion from the import. If the loader inserted a module and the load fails, it must be removed by the loader from `sys.modules`; modules already in `sys.modules` before the loader began execution should be left alone (see `importlib.util.module_for_loader()`).

    ローダーはモジュールにいくつかの属性を設定する必要があります。(なお、これらの属性には、モジュールがリロードされた際に変化するものがあります):

    - `__name__`

        The module's fully qualified name. It is `'__main__'` for an executed module.

    - `__file__`

        The location the loader used to load the module. For example, for modules loaded from a .py file this is the filename. It is not set on all modules (e.g. built-in modules).

    - `__cached__`

        The filename of a compiled version of the module's code. It is not set on all modules (e.g. built-in modules).

    - `__path__`

        The list of locations where the package's submodules will be found. Most of the time this is a single directory. The import system passes this attribute to `__import__()` and to finders in the same way as `sys.path` but just for the package. It is not set on non-package modules so it can be used as an indicator that the module is a package.

    - `__package__`

        The fully qualified name of the package the module is in (or the empty string for a top-level module). If the module is a package then this is the same as `__name__`.

    - `__loader__`

        The loader used to load the module.

    `exec_module()` が利用可能な場合、後方互換な機能が提供されます。

    バージョン 3.4 で変更: Raise `ImportError` when called instead of `NotImplementedError`. Functionality provided when `exec_module()` is available.

    バージョン 3.4 で非推奨: モジュールをロードするための推奨される API は、 `exec_module()` (および `create_module()`) です。ローダーは `load_module()` の代わりにそれを実装するべきです。 `exec_module()` が実装されている場合、インポート機構は `load_module()` の他のすべての責任を肩代わりします。

  module_repr(module)

    A legacy method which when implemented calculates and returns the given module's representation, as a string. The module type's default `__repr__()` will use the result of this method as appropriate.

    バージョン 3.3 で追加.

    バージョン 3.4 で変更: Made optional instead of an abstractmethod.

    バージョン 3.4 で非推奨: The import machinery now takes care of this automatically.

class importlib.abc.ResourceLoader

  loader の抽象基底クラスで、ストレージバックエンドから任意のリソースをロードするオプションの PEP 302 プロトコルを実装します。

  バージョン 3.7 で非推奨: This ABC is deprecated in favour of supporting resource loading through `importlib.resources.abc.ResourceReader`.

  abstractmethod get_data(path)

    path に割り当てられたデータのバイト列を返す抽象メソッドです。任意のデータを保管できるファイル的なストレージバックエンドをもつローダーは、この抽象メソッドを実装して、保管されたデータに直接アクセスさせるようにできます。 path が見つからなければ `OSError` を送出する必要があります。 path は、モジュールの `__file__` 属性を使って、またはパッケージの `__path__` の要素を使って、構成されることが期待されます。

    バージョン 3.4 で変更: `NotImplementedError` の代わりに `OSError` を送出します。

class importlib.abc.InspectLoader

  loader の抽象基底クラスで、ローダーがモジュールを検査するためのオプションの PEP 302 プロトコルを実装します。

  get_code(fullname)

    モジュールの `code` オブジェクトを返すか、 (例えば組み込みモジュールの場合に) モジュールがコードオブジェクトを持たなければ `None` を返します。要求されたモジュールをローダーが見つけられなかった場合は `ImportError` を送出します。

    注釈

    このメソッドにはデフォルト実装がありますが、とはいえパフォーマンスのために、可能ならばオーバライドしたほうが良いです。

    バージョン 3.4 で変更: このメソッドはもはや抽象メソッドではなく、具象実装が提供されます。

  abstractmethod get_source(fullname)

    モジュールのソースを返す抽象メソッドです。これは認識されたすべての行セパレータを `'\n'` 文字に変換し、 universal newlines を使ったテキスト文字列として返されます。利用できるソースがなければ (例えば組み込みモジュール)、 `None` を返します。指定されたモジュールが見つからなければ、 `ImportError` を送出します。

    バージョン 3.4 で変更: `NotImplementedError` の代わりに `ImportError` を送出します。

  is_package(fullname)

    モジュールがパッケージであれば True を返し、そうでなければ False を返すオプションのメソッドです。 ローダー がモジュールを見つけられなかったなら `ImportError` が送出されます。

    バージョン 3.4 で変更: `NotImplementedError` の代わりに `ImportError` を送出します。

  static source_to_code(data, path='<string>')

    Python のソースからコードオブジェクトを作ります。

    data 引数は `compile()` 関数がサポートするもの (すなわち文字列かバイト) なら何でも構いません。path 引数はソースコードの元々の場所への "パス" でなければなりませんが、抽象概念 (例えば zip ファイル内の場所) でも構いません。

    結果のコードオブジェクトを使って、 `exec(code, module.__dict__)` を呼ぶことでモジュール内でコードを実行できます。

    バージョン 3.4 で追加.

    バージョン 3.5 で変更: スタティックメソッドになりました。

  exec_module(module)

    `Loader.exec_module()` の実装です。

    バージョン 3.4 で追加.

  load_module(fullname)

    `Loader.load_module()` の実装です。

    バージョン 3.4 で非推奨: 代わりに `exec_module()` を使用してください。

class importlib.abc.ExecutionLoader

  `InspectLoader` から継承された抽象基底クラスで、実装されていれば、モジュールをスクリプトとして実行する助けになります。この抽象基底クラスはオプションの PEP 302 プロトコルを表します。

  abstractmethod get_filename(fullname)

    指定されたモジュールの `__file__` の値を返す抽象メソッドです。利用できるパスがなければ、 `ImportError` が送出されます。

    ソースコードが利用できるなら、そのモジュールのロードにバイトコードが使われたかにかかわらず、このメソッドはそのソースファイルへのパスを返す必要があります。

    バージョン 3.4 で変更: `NotImplementedError` の代わりに `ImportError` を送出します。

class importlib.abc.FileLoader(fullname, path)

  `ResourceLoader` と `ExecutionLoader` から継承された抽象基底クラスで、 `ResourceLoader.get_data()` および `ExecutionLoader.get_filename()` の具象実装を提供します。

  fullname 引数は、ローダーが解決しようとするモジュールの、完全に解決された名前です。path 引数は、モジュールのファイルへのパスです。

  バージョン 3.3 で追加.

  name

    ローダーが扱えるモジュールの名前です。

  path

    モジュールのファイルへのパスです。

  load_module(fullname)

    親クラスの `load_module()` を呼び出します。

    バージョン 3.4 で非推奨: 代わりに `Loader.exec_module()` を使用してください。

  abstractmethod get_filename(fullname)

    `path` を返します。

  abstractmethod get_data(path)

    path をバイナリファイルとして読み込み、そのバイト列を返します。

class importlib.abc.SourceLoader

  ソース (オプションでバイトコード) ファイルのロードを実装する抽象基底クラスです。このクラスは、 `ResourceLoader` と `ExecutionLoader` の両方を継承し、以下の実装が必要です:

  - `ResourceLoader.get_data()`

  - `ExecutionLoader.get_filename()`

      ソースファイルへのパスのみを返す必要があります。ソースなしのロードはサポートされていません。

  このクラスでこれらの抽象メソッドを定義することで、バイトコードファイルを追加でサポートします。これらのメソッドを定義しなければ (またはそのモジュールが `NotImplementedError` を送出すれば)、このローダーはソースコードに対してのみ働きます。これらのメソッドを実装することで、ローダーはソースとバイトコードファイル の組み合わせ に対して働きます。バイトコードのみを与えた ソースのない ロードは認められません。バイトコードファイルは、 Python コンパイラによる解析の工程をなくして速度を上げる最適化です。ですから、バイトコード特有の API は公開されていません。

  path_stats(path)

    指定されたパスについてのメタデータを含む `dict` を返す、オプションの抽象メソッドです。サポートされる辞書のキーは:

    - `'mtime'` (必須): ソースコードの更新時刻を表す整数または浮動小数点数です。

    - `'size'` (任意): バイト数で表したソースコードのサイズです。

    未来の拡張のため、辞書内の他のキーは無視されます。パスが扱えなければ、 `OSError` が送出されます。

    バージョン 3.3 で追加.

    バージョン 3.4 で変更: `NotImplementedError` の代わりに `OSError` を送出します。

  path_mtime(path)

    指定されたパスの更新時刻を返す、オプションの抽象メソッドです。

    バージョン 3.3 で非推奨: このメソッドは廃止され、 `path_stats()` が推奨されます。このモジュールを実装する必要はありませんが、互換性のため現在も利用できます。パスが扱えなければ、 `OSError` が送出されます。

    バージョン 3.4 で変更: `NotImplementedError` の代わりに `OSError` を送出します。

  set_data(path, data)

    ファイルパスに指定されたバイト列を書き込むオプションの抽象メソッドです。存在しない中間ディレクトリがあれば、自動で作成されます。

    When writing to the path fails because the path is read-only (`errno.EACCES`/`PermissionError`), do not propagate the exception.

    バージョン 3.4 で変更: 呼ばれたときに `NotImplementedError` を送出することは最早ありません。

  get_code(fullname)

    `InspectLoader.get_code()` の具象実装です。

  exec_module(module)

    `Loader.exec_module()` の具象実装です。

    バージョン 3.4 で追加.

  load_module(fullname)

    `Loader.load_module()` の具象実装です。

    バージョン 3.4 で非推奨: 代わりに `exec_module()` を使用してください。

  get_source(fullname)

    `InspectLoader.get_source()` の具象実装です。

  is_package(fullname)

    `InspectLoader.is_package()` の具象実装です。モジュールは、次の 両方 を満たすならパッケージであると決定されます。モジュールの (`ExecutionLoader.get_filename()` で与えられる) ファイルパスが、ファイル拡張子を除くと `__init__` という名のファイルであること。モジュール名自体が `__init__` で終わらないこと。

## `importlib.machinery` -- インポータおよびパスフック

ソースコード: Lib/importlib/machinery.py

このモジュールには、 `import` がモジュールを検索してロードするのに役立つ様々なオブジェクトがあります。

importlib.machinery.SOURCE_SUFFIXES

  認識されているソースモジュールのファイル接尾辞を表す文字列のリストです。

  バージョン 3.3 で追加.

importlib.machinery.DEBUG_BYTECODE_SUFFIXES

  最適化されていないバイトコードモジュールのファイル接尾辞を表す文字列のリストです。

  バージョン 3.3 で追加.

  バージョン 3.5 で非推奨: 代わりに `BYTECODE_SUFFIXES` を使ってください。

importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES

  最適化されたバイトコードモジュールのファイル接尾辞を表す文字列のリストです。

  バージョン 3.3 で追加.

  バージョン 3.5 で非推奨: 代わりに `BYTECODE_SUFFIXES` を使ってください。

importlib.machinery.BYTECODE_SUFFIXES

  認識されているバイトコードモジュールのファイル接尾辞を表す文字列のリストです (先頭のドットを含みます)。

  バージョン 3.3 で追加.

  バージョン 3.5 で変更: この値は `__debug__` に依存しなくなりました。

importlib.machinery.EXTENSION_SUFFIXES

  認識されている最適化された拡張モジュールのファイル接尾辞を表す文字列のリストです。

  バージョン 3.3 で追加.

importlib.machinery.all_suffixes()

  標準のインポート機構によって認識されているすべてのファイル接尾辞を表す文字列の組み合わせられたリストを返します。これが役立つのは、あるファイルシステムパスがモジュールを参照する可能性があるかだけを知りたくて、そのモジュールの種類を詳しく知る必要はないコード (例えば `inspect.getmodulename()`) です。

  バージョン 3.3 で追加.

class importlib.machinery.BuiltinImporter

  組み込みモジュールの importer です。すべての既知のモジュールは `sys.builtin_module_names` に列挙されています。このクラスは `importlib.abc.MetaPathFinder` および `importlib.abc.InspectLoader` 抽象基底クラスを実装します。

  インスタンス化の必要性を軽減するため、このクラスにはクラスメソッドだけが定義されています。

  バージョン 3.5 で変更: PEP 489 の一環として、ビルトインインポーターは `Loader.create_module()` と `Loader.exec_module()` を実装しています。

class importlib.machinery.FrozenImporter

  フリーズされたモジュールの インポーター です。このクラスは `importlib.abc.MetaPathFinder` および `importlib.abc.InspectLoader` 抽象基底クラスを実装します。

  インスタンス化の必要性を軽減するため、このクラスにはクラスメソッドだけが定義されています。

  バージョン 3.4 で変更: Gained `create_module()` and `exec_module()` methods.

class importlib.machinery.WindowsRegistryFinder

  Windows レジストリで宣言されたモジュールの finder です。このクラスは `importlib.abc.MetaPathFinder` 抽象基底クラスを実装します。

  インスタンス化の必要性を軽減するため、このクラスにはクラスメソッドだけが定義されています。

  バージョン 3.3 で追加.

  バージョン 3.6 で非推奨: 代わりに `site` の設定を使ってください。 Python の将来のバージョンでは、デフォルトでこのファインダーが使えなくなるかもしれません。

class importlib.machinery.PathFinder

  `sys.path` およびパッケージの `__path__` 属性の Finder です。このクラスは `importlib.abc.MetaPathFinder` 抽象基底クラスを実装します。

  インスタンス化の必要性を軽減するため、このクラスにはクラスメソッドだけが定義されています。

  classmethod find_spec(fullname, path=None, target=None)

    `sys.path` または定義されていれば path から、 fullname で指定されたモジュールの スペック の検索を試みるクラスメソッドです。検索されるそれぞれのパスエントリに対して `sys.path_importer_cache` が検査されます。偽でないオブジェクトが見つかれば、それが目的のモジュールを検索するための パスエントリ・ファインダー として使われます。 `sys.path_importer_cache` に目的のエントリが見つからなければ、パスエントリに対するファインダーが `sys.path_hooks` から検索され、見つかれば、それが `sys.path_importer_cache` に保管されるとともに、モジュールについて問い合わせられます。それでもファインダーが見つからなければ `None` が保管され、また返されます。

    バージョン 3.4 で追加.

    バージョン 3.5 で変更: もしカレントワーキングディレクトリ -- 空の文字列によって表されている -- がすでに有効でなければ、 `None` が返されますが値は `sys.path_importer_cache` にキャッシュされません。

  classmethod find_module(fullname, path=None)

    A legacy wrapper around `find_spec()`.

    バージョン 3.4 で非推奨: Use `find_spec()` instead.

  classmethod invalidate_caches()

    Calls `importlib.abc.PathEntryFinder.invalidate_caches()` on all finders stored in `sys.path_importer_cache` that define the method. Otherwise entries in `sys.path_importer_cache` set to `None` are deleted.

    バージョン 3.7 で変更: Entries of `None` in `sys.path_importer_cache` are deleted.

  バージョン 3.4 で変更: `''` (すなわち空の文字列) に対してはカレントワーキングディレクトリとともに `sys.path_hooks` のオブジェクトを呼び出します。

class importlib.machinery.FileFinder(path, *loader_details)

  ファイルシステムからの結果をキャッシュする `importlib.abc.PathEntryFinder` の具象実装です。

  path 引数は検索を担当するファインダーのディレクトリです。

  loader_details 引数は、可変個の 2 要素タプルで、それぞれがローダーとローダーが認識するファイル接尾辞のシーケンスとを含みます。ローダーは、呼び出し可能でモジュール名と見つかったファイルのパスとの 2 引数を受け付けることを期待されます。

  ファインダーはモジュール検索のたびに stat を呼び出し、必要に応じてディレクトリの内容をキャッシュすることで、コードキャッシュが古くなっていないことを確かめます。キャッシュの古さはオペレーティングシステムのファイルシステムのステート情報の粒度に依存しますから、モジュールを検索し、新しいファイルを作成し、その後に新しいファイルが表すモジュールを検索する、という競合状態の可能性があります。この操作が stat の呼び出しの粒度に収まるほど速く起こると、モジュールの検索が失敗します。これを防ぐためには、モジュールを動的に作成する際に、必ず `importlib.invalidate_caches()` を呼び出してください。

  バージョン 3.3 で追加.

  path

    ファインダーが検索されるパスです。

  find_spec(fullname, target=None)

    `path` 内で fullname を扱うスペックの探索を試みます。

    バージョン 3.4 で追加.

  find_loader(fullname)

    Attempt to find the loader to handle fullname within `path`.

    バージョン 3.10 で非推奨: Use `find_spec()` instead.

  invalidate_caches()

    内部キャッシュを完全に消去します。

  classmethod path_hook(*loader_details)

    A class method which returns a closure for use on `sys.path_hooks`. An instance of `FileFinder` is returned by the closure using the path argument given to the closure directly and loader_details indirectly.

    クロージャへの引数が存在するディレクトリでなければ、 `ImportError` が送出されます。

class importlib.machinery.SourceFileLoader(fullname, path)

  `importlib.abc.FileLoader` を継承し、その他いくつかのメソッドの具象実装を提供する、 `importlib.abc.SourceLoader` の具象実装です。

  バージョン 3.3 で追加.

  name

    このローダーが扱うモジュールの名前です。

  path

    ソースファイルへのパスです。

  is_package(fullname)

    `path` がパッケージを表すとき `True` を返します。

  path_stats(path)

    `importlib.abc.SourceLoader.path_stats()` の具象実装です。

  set_data(path, data)

    `importlib.abc.SourceLoader.set_data()` の具象実装です。

  load_module(name=None)

    ロードするモジュールの名前指定がオプションの、 `importlib.abc.Loader.load_module()` の具象実装です。

    バージョン 3.6 で非推奨: 代わりに `importlib.abc.Loader.exec_module()` を使用してください。

class importlib.machinery.SourcelessFileLoader(fullname, path)

  バイトコードファイル (すなわちソースコードファイルが存在しない) をインポートできる `importlib.abc.FileLoader` の具象実装です。

  注意として、バイトコードを直接使う (つまりソースコードファイルがない) と、そのモジュールはすべての Python 実装では使用できないし、新しいバージョンの Python ではバイトコードフォーマットが変更されていたら使用できません。

  バージョン 3.3 で追加.

  name

    ローダーが扱うモジュールの名前です。

  path

    バイトコードファイルへのパスです。

  is_package(fullname)

    そのモジュールがパッケージであるかを `path` に基づいて決定します。

  get_code(fullname)

    `path` から作成された `name` のコードオブジェクトを返します。

  get_source(fullname)

    このローダーが使われたとき、バイトコードファイルのソースがなければ `None` を返します。

  load_module(name=None)

  ロードするモジュールの名前指定がオプションの、 `importlib.abc.Loader.load_module()` の具象実装です。

  バージョン 3.6 で非推奨: 代わりに `importlib.abc.Loader.exec_module()` を使用してください。

class importlib.machinery.ExtensionFileLoader(fullname, path)

  拡張モジュールのための `importlib.abc.ExecutionLoader` の具象実装です。

  fullname 引数はローダーがサポートするモジュールの名前を指定します。path 引数は拡張モジュールのファイルへのパスです。

  バージョン 3.3 で追加.

  name

    ローダーがサポートするモジュールの名前です。

  path

    拡張モジュールへのパスです。

  create_module(spec)

    与えられたスペックから PEP 489 に従ってモジュールオブジェクトを作成します。

    バージョン 3.5 で追加.

  exec_module(module)

    与えられたモジュールオブジェクトを PEP 489 に従って初期化します。

    バージョン 3.5 で追加.

  is_package(fullname)

    `EXTENSION_SUFFIXES` に基づいて、ファイルパスがパッケージの `__init__` モジュールを指していれば `True` を返します。

  get_code(fullname)

    拡張モジュールにコードオブジェクトがなければ `None` を返します。

  get_source(fullname)

    拡張モジュールにソースコードがなければ `None` を返します。

  get_filename(fullname)

    `path` を返します。

    バージョン 3.4 で追加.

class importlib.machinery.NamespaceLoader(name, path, path_finder)

  A concrete implementation of `importlib.abc.InspectLoader` for namespace packages. This is an alias for a private class and is only made public for introspecting the `__loader__` attribute on namespace packages:

      >>> from importlib.machinery import NamespaceLoader
      >>> import my_namespace
      >>> isinstance(my_namespace.__loader__, NamespaceLoader)
      True
      >>> import importlib.abc
      >>> isinstance(my_namespace.__loader__, importlib.abc.Loader)
      True

  バージョン 3.11 で追加.

class importlib.machinery.ModuleSpec(name, loader, *, origin=None, loader_state=None, is_package=None)

  モジュールのインポートシステムに関する状態の仕様。 これは通常はモジュールの `__spec__` 属性として公開されています。 この後の解説では、モジュールオブジェクトから直接利用できる属性で、それぞれの仕様に対応しているものの名前が括弧書きで書かれています。 例えば、 `module.__spec__.origin == module.__file__` です。 ただし、属性の 値 はたいていは同一ですが、2つのオブジェクトどうしは同期されないため、異なっている可能性があることに注意してください。 例えば、モジュールの `__file__` を実行時に更新できますが、モジュールの `__spec__.origin` に自動的には反映されませんし、逆もまた同様です。

  バージョン 3.4 で追加.

  name

  (`__name__`)

  モジュールの完全修飾名。 finder は常にこの属性を空でない文字列に設定する必要があります。

  loader

  (`__loader__`)

  The loader used to load the module. The finder should always set this attribute.

  origin

  (`__file__`)

  The location the loader should use to load the module. For example, for modules loaded from a .py file this is the filename. The finder should always set this attribute to a meaningful value for the loader to use. In the uncommon case that there is not one (like for namespace packages), it should be set to `None`.

  submodule_search_locations

  (`__path__`)

  The list of locations where the package's submodules will be found. Most of the time this is a single directory. The finder should set this attribute to a list, even an empty one, to indicate to the import system that the module is a package. It should be set to `None` for non-package modules. It is set automatically later to a special object for namespace packages.

  loader_state

  The finder may set this attribute to an object containing additional, module-specific data to use when loading the module. Otherwise it should be set to `None`.

  cached

  (`__cached__`)

  The filename of a compiled version of the module's code. The finder should always set this attribute but it may be `None` for modules that do not need compiled code stored.

  parent

  (`__package__`)

  (Read-only) The fully qualified name of the package the module is in (or the empty string for a top-level module). If the module is a package then this is the same as `name`.

  has_location
  `True` if the spec's `origin` refers to a loadable location,

    `False` otherwise. This value impacts how `origin` is interpreted and how the module's `__file__` is populated.

## `importlib.util` -- インポータのためのユーティリティコード

ソースコード: Lib/importlib/util.py

このモジュールには、 インポーター の構築を助ける様々なオブジェクトがあります。

importlib.util.MAGIC_NUMBER

  バイトコードバージョン番号を表しているバイト列。バイトコードのロード／書き込みについてヘルプが必要なら `importlib.abc.SourceLoader` を参照してください。

  バージョン 3.4 で追加.

importlib.util.cache_from_source(path, debug_override=None, *, optimization=None)

  ソース path に関連付けられたバイトコンパイルされたファイルの PEP 3147/PEP 488 パスを返します。例えば、 path が `/foo/bar/baz.py` なら、 Python 3.2 の場合返り値は `/foo/bar/__pycache__/baz.cpython-32.pyc` になります。 `cpython-32` という文字列は、現在のマジックタグから得られます (マジックタグについては `get_tag()` を参照; `sys.implementation.cache_tag` が未定義なら `NotImplementedError` が送出されます。)

  optimization パラメータは、バイトコードファイルの最適化レベルを指定するために使われます。空文字列は最適化しないことを表します。したがって、 optimization が `''` のとき `/foo/bar/baz.py` に対して `/foo/bar/__pycache__/baz.cpython-32.pyc` というバイトコードパスが返ります。 `None` にするとインタープリタの最適化レベルが使われます。それ以外では値の文字列表現が使われます。したがって、 optimization が `2` のとき `/foo/bar/baz.py` に対して `/foo/bar/__pycache__/baz.cpython-32.opt-2.pyc` というバイトコードパスが返ります。 optimization の文字列表現は英数字だけが可能で、そうでなければ `ValueError` が上げられます。

  debug_override パラメータは deprecated で、システムの `__debug__` 値をオーバーライドするために使用できます。 `True` 値は optimization を空文字列に設定するのと等価です。 `False` 値は optimization を `1` に設定するのと同等です。もし debug_override と optimization のどちらも `None` 以外であれば `TypeError` が上げられます。

  バージョン 3.4 で追加.

  バージョン 3.5 で変更: optimization パラメータが追加され、 debug_override パラメータは deprecated になりました。

  バージョン 3.6 で変更: path-like object を受け入れるようになりました。

importlib.util.source_from_cache(path)

  PEP 3147 ファイル名への path が与えられると、関連するソースコードのファイルパスを返します。例えば、 path が `/foo/bar/__pycache__/baz.cpython-32.pyc` なら、返されるパスは `/foo/bar/baz.py` になります。 path は存在する必要はありませんが、 PEP 3147 または PEP 488 フォーマットに一致しない場合は `ValueError` が送出されます。 `sys.implementation.cache_tag` が定義されていない場合、 `NotImplementedError` が送出されます。

  バージョン 3.4 で追加.

  バージョン 3.6 で変更: path-like object を受け入れるようになりました。

importlib.util.decode_source(source_bytes)

  与えられたソースコードを表すバイト列をデコードして、文字列としてそれを一般的な改行形式 (universal newlines) で返します (`importlib.abc.InspectLoader.get_source()` で要求されるように)。

  バージョン 3.4 で追加.

importlib.util.resolve_name(name, package)

  相対的なモジュール名を解決して絶対的なものにします。

  name の先頭にドットがなければ、単に name が返されます。これにより、例えば `importlib.util.resolve_name('sys', __spec__.parent)` を使うときに package 変数が必要かどうかを確認する必要がなくなります。

  name が相対的なモジュール名であるにもかかわらず package が偽値 (例えば `None` や空文字列) ならば、 `ImportError` が送出されます。相対的な名前がそれを含むパッケージから抜け出る (例えば `spam` パッケージ内から `..bacon` を要求する) 場合にも `ImportError` が送出されます。

  バージョン 3.3 で追加.

  バージョン 3.9 で変更: To improve consistency with import statements, raise `ImportError` instead of `ValueError` for invalid relative import attempts.

importlib.util.find_spec(name, package=None)

  Find the spec for a module, optionally relative to the specified package name. If the module is in `sys.modules`, then `sys.modules[name].__spec__` is returned (unless the spec would be `None` or is not set, in which case `ValueError` is raised). Otherwise a search using `sys.meta_path` is done. `None` is returned if no spec is found.

  name がサブモジュールを示している (ドットを含む) 場合、親モジュールは自動的にインポートされます。

  name と package は `import_module()` に対するものと同じように機能します。

  バージョン 3.4 で追加.

  バージョン 3.7 で変更: Raises `ModuleNotFoundError` instead of `AttributeError` if package is in fact not a package (i.e. lacks a `__path__` attribute).

importlib.util.module_from_spec(spec)

  spec と `spec.loader.create_module` に基づいて新しいモジュールを作ります。

  `spec.loader.create_module` が `None` を返さない場合は、既に存在するどの属性もリセットされません。また、 spec にアクセスしたり属性をモジュールに設定したりする際に `AttributeError` 例外が起きても例外は送出されません。

  この関数は、新しいモジュールを作る方法として `types.ModuleType` よりも推奨されます。なぜなら、できるだけ多くのインポートコントロールされた属性をモジュールに設定するために spec が使用されるからです。

  バージョン 3.5 で追加.

@importlib.util.module_for_loader

  A decorator for `importlib.abc.Loader.load_module()` to handle selecting the proper module object to load with. The decorated method is expected to have a call signature taking two positional arguments (e.g. `load_module(self, module)`) for which the second argument will be the module object to be used by the loader. Note that the decorator will not work on static methods because of the assumption of two arguments.

  The decorated method will take in the name of the module to be loaded as expected for a loader. If the module is not found in `sys.modules` then a new one is constructed. Regardless of where the module came from, `__loader__` set to self and `__package__` is set based on what `importlib.abc.InspectLoader.is_package()` returns (if available). These attributes are set unconditionally to support reloading.

  If an exception is raised by the decorated method and a module was added to `sys.modules`, then the module will be removed to prevent a partially initialized module from being in left in `sys.modules`. If the module was already in `sys.modules` then it is left alone.

  バージョン 3.3 で変更: `__loader__` and `__package__` are automatically set (when possible).

  バージョン 3.4 で変更: Set `__name__`, `__loader__` `__package__` unconditionally to support reloading.

  バージョン 3.4 で非推奨: The import machinery now directly performs all the functionality provided by this function.

@importlib.util.set_loader

  A decorator for `importlib.abc.Loader.load_module()` to set the `__loader__` attribute on the returned module. If the attribute is already set the decorator does nothing. It is assumed that the first positional argument to the wrapped method (i.e. `self`) is what `__loader__` should be set to.

  バージョン 3.4 で変更: Set `__loader__` if set to `None`, as if the attribute does not exist.

  バージョン 3.4 で非推奨: The import machinery takes care of this automatically.

@importlib.util.set_package

  A decorator for `importlib.abc.Loader.load_module()` to set the `__package__` attribute on the returned module. If `__package__` is set and has a value other than `None` it will not be changed.

  バージョン 3.4 で非推奨: The import machinery takes care of this automatically.

importlib.util.spec_from_loader(name, loader, *, origin=None, is_package=None)

  この関数は、スペックに不足している情報を埋めるために `ModuleSpec` のような利用可能な loader API を使います。

  バージョン 3.4 で追加.

importlib.util.spec_from_file_location(name, location, *, loader=None, submodule_search_locations=None)

  ファイルへのパスにもとづいて `ModuleSpec` インスタンスを生成するためのファクトリー関数。不足している情報は、ローダー API を利用してスペックから得られる情報と、モジュールがファイルベースであるという暗黙的な情報によって埋められます。

  バージョン 3.4 で追加.

  バージョン 3.6 で変更: path-like object を受け入れるようになりました。

importlib.util.source_hash(source_bytes)

  Return the hash of source_bytes as bytes. A hash-based `.pyc` file embeds the `source_hash()` of the corresponding source file's contents in its header.

  バージョン 3.7 で追加.

class importlib.util.LazyLoader(loader)

  モジュールが属性アクセスできるようになるまで、モジュールのローダーの実行を遅延するクラス。

  This class only works with loaders that define `exec_module()` as control over what module type is used for the module is required. For those same reasons, the loader's `create_module()` method must return `None` or a type for which its `__class__` attribute can be mutated along with not using slots. Finally, modules which substitute the object placed into `sys.modules` will not work as there is no way to properly replace the module references throughout the interpreter safely; `ValueError` is raised if such a substitution is detected.

  注釈

  起動時間が重要なプロジェクトでは、もし決して使われないモジュールがあれば、このクラスを使ってモジュールをロードするコストを最小化できるかもしれません。スタートアップ時間が重要でないプロジェクトでは、遅延されたロードの際に発生して文脈の外で起こるエラーメッセージのため、このクラスの使用は 著しく 推奨されません。

  バージョン 3.5 で追加.

  バージョン 3.6 で変更: Began calling `create_module()`, removing the compatibility warning for `importlib.machinery.BuiltinImporter` and `importlib.machinery.ExtensionFileLoader`.

  classmethod factory(loader)

    遅延ローダを生成する callable を返すクラスメソッド。これは、ローダーをインスタンスとしてではなくクラスとして渡すような状況において使われることを意図しています。

        suffixes = importlib.machinery.SOURCE_SUFFIXES
        loader = importlib.machinery.SourceFileLoader
        lazy_loader = importlib.util.LazyLoader.factory(loader)
        finder = importlib.machinery.FileFinder(path, (lazy_loader, suffixes))

## 使用例

### プログラムからのインポート

プログラムからモジュールをインポートするには、 `importlib.import_module()` を使ってください。

    import importlib

    itertools = importlib.import_module('itertools')

### モジュールがインポートできるか確認する

インポートを実際に行わずに、あるモジュールがインポートできるかを知る必要がある場合は、 `importlib.util.find_spec()` を使ってください。

Note that if `name` is a submodule (contains a dot), `importlib.util.find_spec()` will import the parent module.

    import importlib.util
    import sys

    # For illustrative purposes.
    name = 'itertools'

    if name in sys.modules:
        print(f"{name!r} already in sys.modules")
    elif (spec := importlib.util.find_spec(name)) is not None:
        # If you chose to perform the actual import ...
        module = importlib.util.module_from_spec(spec)
        sys.modules[name] = module
        spec.loader.exec_module(module)
        print(f"{name!r} has been imported")
    else:
        print(f"can't find the {name!r} module")

### ソースファイルから直接インポートする

To import a Python source file directly, use the following recipe:

    import importlib.util
    import sys

    # For illustrative purposes.
    import tokenize
    file_path = tokenize.__file__
    module_name = tokenize.__name__

    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    sys.modules[module_name] = module
    spec.loader.exec_module(module)

### Implementing lazy imports

The example below shows how to implement lazy imports:

    >>> import importlib.util
    >>> import sys
    >>> def lazy_import(name):
    ...     spec = importlib.util.find_spec(name)
    ...     loader = importlib.util.LazyLoader(spec.loader)
    ...     spec.loader = loader
    ...     module = importlib.util.module_from_spec(spec)
    ...     sys.modules[name] = module
    ...     loader.exec_module(module)
    ...     return module
    ...
    >>> lazy_typing = lazy_import("typing")
    >>> #lazy_typing is a real module object,
    >>> #but it is not loaded in memory yet.
    >>> lazy_typing.TYPE_CHECKING
    False

### インポーターのセットアップ

For deep customizations of import, you typically want to implement an importer. This means managing both the finder and loader side of things. For finders there are two flavours to choose from depending on your needs: a meta path finder or a path entry finder. The former is what you would put on `sys.meta_path` while the latter is what you create using a path entry hook on `sys.path_hooks` which works with `sys.path` entries to potentially create a finder. This example will show you how to register your own importers so that import will use them (for creating an importer for yourself, read the documentation for the appropriate classes defined within this package):

    import importlib.machinery
    import sys

    # For illustrative purposes only.
    SpamMetaPathFinder = importlib.machinery.PathFinder
    SpamPathEntryFinder = importlib.machinery.FileFinder
    loader_details = (importlib.machinery.SourceFileLoader,
                      importlib.machinery.SOURCE_SUFFIXES)

    # Setting up a meta path finder.
    # Make sure to put the finder in the proper location in the list in terms of
    # priority.
    sys.meta_path.append(SpamMetaPathFinder)

    # Setting up a path entry finder.
    # Make sure to put the path hook in the proper location in the list in terms
    # of priority.
    sys.path_hooks.append(SpamPathEntryFinder.path_hook(loader_details))

### Approximating `importlib.import_module()`

Import itself is implemented in Python code, making it possible to expose most of the import machinery through importlib. The following helps illustrate the various APIs that importlib exposes by providing an approximate implementation of `importlib.import_module()`:

    import importlib.util
    import sys

    def import_module(name, package=None):
        """An approximate implementation of import."""
        absolute_name = importlib.util.resolve_name(name, package)
        try:
            return sys.modules[absolute_name]
        except KeyError:
            pass

        path = None
        if '.' in absolute_name:
            parent_name, _, child_name = absolute_name.rpartition('.')
            parent_module = import_module(parent_name)
            path = parent_module.__spec__.submodule_search_locations
        for finder in sys.meta_path:
            spec = finder.find_spec(absolute_name, path)
            if spec is not None:
                break
        else:
            msg = f'No module named {absolute_name!r}'
            raise ModuleNotFoundError(msg, name=absolute_name)
        module = importlib.util.module_from_spec(spec)
        sys.modules[absolute_name] = module
        spec.loader.exec_module(module)
        if path is not None:
            setattr(parent_module, child_name, module)
        return module