importlib --- import の実装

Added in version 3.1.

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


はじめに

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

1 つ目は import 文 (ひいては __import__() 関数) の実装を Python のソースコードで提供することです。 これにより、どの Python インタープリターにも移植できる import の実装を提供します。 また、Python 以外のプログラミング言語による実装よりも理解しやすい実装になります。

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

3 つ目は、Python パッケージのさまざまな側面を管理する追加機能を提供するモジュールを含むことです。

  • importlib.metadata はサードパーティの配布物のメタデータへのアクセスを提供します。

  • importlib.resources は Python パッケージ内のコード以外の「リソース」にアクセスする機能を提供します。

参考

import 文

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

Packages specification

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

__import__() 関数

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

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

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() を呼ぶ必要があるでしょう。

モジュールをインポートできない場合、import_module() は ImportError または ModuleNotFoundError などの適切なサブクラスを送出します。

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

importlib.invalidate_caches()

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

Added in version 3.3.

バージョン 3.10 で変更: 同じ名前空間をすでにインポートした後に、sys.path の別の場所に作成またはインストールされた名前空間パッケージも認識するようになりました。

importlib.reload(module)

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

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

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

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

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

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

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

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

try:
    cache
except NameError:
    cache = {}

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

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

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

Added in version 3.4.

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

警告

この関数はスレッドセーフではありません。 複数のスレッドから呼び出すと、予期しない動作を引き起こすことがあります。 スレッドセーフにモジュールをリロードするには、threading.Lock や他の同期プリミティブの使用を推奨します。

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

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


importlib.abc モジュールは、import が使う主要な抽象基底クラスをすべて含みます。 これらの ABC の実装を支援するため、主要な抽象基底クラスのサブクラスもいくつか提供します。

抽象基底クラス階層:

object
 +-- MetaPathFinder
 +-- PathEntryFinder
 +-- Loader
      +-- ResourceLoader --------+
      +-- InspectLoader          |
           +-- ExecutionLoader --+
                                 +-- FileLoader
                                 +-- SourceLoader
class importlib.abc.MetaPathFinder

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

Added in version 3.3.

バージョン 3.10 で変更: Finder のサブクラスではなくなりました。

find_spec(fullname, path, target=None)

指定されたモジュールの スペック を検索する抽象メソッドです。 トップレベルのインポートの場合、path は None です。 それ以外の場合はサブパッケージやモジュールの検索で、path は親パッケージの __path__ の値です。 スペックが見つからなければ None を返します。 target が渡される場合はモジュールオブジェクトであり、ファインダーが返すスペックをより的確に判断するために使えます。 具体的な MetaPathFinders の実装には、importlib.util.spec_from_loader() が役立つ場合があります。

Added in version 3.4.

invalidate_caches()

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

バージョン 3.4 で変更: 呼び出された際に NotImplemented ではなく None を返すようになりました。

discover(parent=None)

指定された parent モジュールのスペックを使い、見つかる可能性のあるスペックを検索するオプションのメソッドです。 parent が None の場合、MetaPathFinder.discover() はトップレベルのモジュールを検索します。

見つかる可能性のあるスペックのイテラブルを返します。

parent がパッケージモジュールでなければ ValueError を送出します。

警告

このメソッドは非常に多くのオブジェクトを yield する可能性があり、これらの値を計算する際に入出力操作を行うこともあります。

そのため、通常は結果の値を必要になったときにその都度計算するのが望ましいでしょう。 したがって、戻り値として保証されるのは イテラブル であることだけであり、list や他の コレクション 型とは限りません。

Added in version 3.15.

class importlib.abc.PathEntryFinder

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

Added in version 3.3.

バージョン 3.10 で変更: Finder のサブクラスではなくなりました。

find_spec(fullname, target=None)

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

Added in version 3.4.

invalidate_caches()

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

discover(parent=None)

指定された parent モジュールのスペックを使い、見つかる可能性のあるスペックを検索するオプションのメソッドです。 parent が None の場合、PathEntryFinder.discover() はトップレベルのモジュールを検索します。

見つかる可能性のあるスペックのイテラブルを返します。

parent がパッケージモジュールでなければ ValueError を送出します。

警告

このメソッドは非常に多くのオブジェクトを yield する可能性があり、これらの値を計算する際に入出力操作を行うこともあります。

そのため、通常は結果の値を必要になったときにその都度計算するのが望ましいでしょう。 したがって、戻り値として保証されるのは イテラブル であることだけであり、list や他の コレクション 型とは限りません。

Added in version 3.15.

class importlib.abc.Loader

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

リソースの読み取りをサポートするローダーは、importlib.resources.abc.ResourceReader で定められた get_resource_reader() メソッドを実装する必要があります。

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

バージョン 3.15 で変更: load_module() メソッドを削除しました。

create_module(spec)

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

Added in version 3.4.

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

exec_module(module)

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

Added in version 3.4.

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

class importlib.abc.ResourceLoader

TraversableResources に取って代わられました

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

バージョン 3.7 で非推奨: この ABC は非推奨です。 代わりに importlib.resources.abc.TraversableResources を通じてリソースをロードしてください。 このクラスは、このモジュールの他の ABC との後方互換性のためだけに存在します。

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>', fullname=None)

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

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

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

オプションの fullname 引数はモジュール名を指定します。 構文の警告をモジュール名で曖昧さなく フィルタリング するために必要です。

Added in version 3.4.

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

Added in version 3.15: fullname 引数を追加しました。

exec_module(module)

Loader.exec_module() の実装です。

Added in version 3.4.

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 引数は、モジュールのファイルへのパスです。

Added in version 3.3.

バージョン 3.15 で変更: load_module() メソッドを削除しました。

name

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

path

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

abstractmethod get_filename(fullname)

path を返します。

abstractmethod get_data(path)

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

class importlib.abc.SourceLoader

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

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

バージョン 3.15 で変更: load_module() メソッドを削除しました。

path_stats(path)

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

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

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

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

Added in version 3.3.

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

path_mtime(path)

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

バージョン 3.3 で非推奨: このメソッドは非推奨で、代わりに path_stats() を使います。 実装する必要はありませんが、互換性のために引き続き利用できます。 パスを扱えない場合は OSError を送出してください。

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

set_data(path, data)

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

パスが読み取り専用のために書き込みが失敗した場合 (errno.EACCES/PermissionError)、例外を伝播させないでください。

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

get_code(fullname)

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

exec_module(module)

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

Added in version 3.4.

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

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

Added in version 3.3.

importlib.machinery.DEBUG_BYTECODE_SUFFIXES

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

Added in version 3.3.

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

importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES

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

Added in version 3.3.

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

importlib.machinery.BYTECODE_SUFFIXES

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

Added in version 3.3.

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

importlib.machinery.EXTENSION_SUFFIXES

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

Added in version 3.3.

importlib.machinery.all_suffixes()

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

Added in version 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 で変更: create_module() と exec_module() メソッドを追加しました。

class importlib.machinery.WindowsRegistryFinder

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

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

Added in version 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 が保管され、また返されます。

Added in version 3.4.

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

classmethod invalidate_caches()

sys.path_importer_cache に保存されたファインダーのうち、このメソッドを定義しているすべてのファインダーで importlib.abc.PathEntryFinder.invalidate_caches() を呼び出します。 一方、sys.path_importer_cache の値が None のエントリーは削除します。

バージョン 3.7 で変更: sys.path_importer_cache の None のエントリーを削除するようになりました。

バージョン 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() を呼び出してください。

Added in version 3.3.

path

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

find_spec(fullname, target=None)

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

Added in version 3.4.

invalidate_caches()

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

classmethod path_hook(*loader_details)

sys.path_hooks で使うクロージャを返すクラスメソッドです。 クロージャは、直接渡されたパス引数と、間接的に渡された loader_details を使って、FileFinder インスタンスを返します。

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

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

名前空間パッケージ のパス (module.__path__) を表します。

__path__ の値が参照されると、必要に応じて再計算されます。 これによりグローバルな状態 (sys.modules) との整合性を保ちます。

name 引数は名前空間モジュールの名前です。

path 引数はパスの初期値です。

path_finder 引数は、パスの値を再計算するための呼び出し可能オブジェクトです。 シグネチャは importlib.abc.MetaPathFinder.find_spec() と同じです。

親の module.__path__ 属性が更新されると、パスの値を再計算します。

親モジュールが sys.modules にない場合、ModuleNotFoundError を送出します。

トップレベルのモジュールでは、親モジュールのパスに相当するものは sys.path です。

注釈

PathFinder.invalidate_caches() は NamespacePath を無効化し、次にアクセスされた際にパスの値を必ず再計算させます。

Added in version 3.15.

class importlib.machinery.SourceFileLoader(fullname, path)

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

Added in version 3.3.

バージョン 3.15 で変更: load_module() メソッドを削除しました。

name

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

path

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

is_package(fullname)

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

path_stats(path)

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

set_data(path, data)

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

class importlib.machinery.SourcelessFileLoader(fullname, path)

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

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

Added in version 3.3.

バージョン 3.15 で変更: load_module() メソッドを削除しました。

name

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

path

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

is_package(fullname)

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

get_code(fullname)

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

get_source(fullname)

このローダーを使う場合、バイトコードファイルにはソースがないため None を返します。

class importlib.machinery.ExtensionFileLoader(fullname, path)

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

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

複数フェーズの初期化 (PEP 489 を参照) を実装していない拡張モジュールは、通常なら正常にインポートできても、デフォルトではサブインタープリタへのインポートに失敗します。

Added in version 3.3.

バージョン 3.12 で変更: サブインタープリタで使うには、複数フェーズの初期化が必要になりました。

name

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

path

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

create_module(spec)

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

Added in version 3.5.

exec_module(module)

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

Added in version 3.5.

is_package(fullname)

EXTENSION_SUFFIXES に基づき、ファイルパスがパッケージの __init__ モジュールを指す場合に True を返します。

get_code(fullname)

拡張モジュールにはコードオブジェクトがないため None を返します。

get_source(fullname)

拡張モジュールにはソースコードがないため None を返します。

get_filename(fullname)

path を返します。

Added in version 3.4.

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

名前空間パッケージ向けの importlib.abc.InspectLoader の具体的な実装です。 非公開クラスの別名であり、名前空間パッケージの __loader__ 属性を調べる目的に限って公開されています。

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

Added in version 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 には自動的に反映されず、逆も同様です。

Added in version 3.4.

name

モジュールの完全修飾名です (module.__name__ を参照)。 ファインダー は、常にこの属性を空でない文字列に設定する必要があります。

loader

モジュールをロードする ローダー です (module.__loader__ を参照)。 ファインダー は常にこの属性を設定する必要があります。

origin

ローダー がモジュールのロードに使う場所です (module.__file__ を参照)。 例えば、.py ファイルからロードするモジュールではファイル名です。 ファインダー は、常に ローダー が使える意味のある値をこの属性に設定する必要があります。 名前空間パッケージなど、該当する場所がない例外的な場合には None に設定してください。

submodule_search_locations

パッケージのサブモジュールを検索する場所を列挙した、文字列の シーケンス です (module.__path__ を参照)。 空の場合もありますが、通常はディレクトリが 1 つだけ含まれます。

モジュールがパッケージであることをインポートシステムに示すには、ファインダー は、この属性を空でもよいのでシーケンスに設定する必要があります。 パッケージでないモジュールでは None にしてください。 名前空間パッケージでは、後で特殊なオブジェクトが自動的に設定されます。

loader_state

ファインダー は、この属性に、モジュールのロードに使う追加のモジュール固有データを格納したオブジェクトを設定できます。 それ以外の場合は None に設定してください。

cached

モジュールのコードをコンパイルしたファイルの名前です。 ファインダー は常にこの属性を設定する必要がありますが、コンパイル済みコードの保存が不要なモジュールでは None にできます。

parent

(読み取り専用) モジュールが属するパッケージの完全修飾名です (トップレベルのモジュールでは空文字列)。 module.__package__ を参照してください。 モジュール自体がパッケージであれば、name と同じです。

has_location

スペックの origin がロード可能な場所を指す場合は True、それ以外は False です。 この値は origin の解釈方法と、モジュールの __file__ の設定方法に影響します。

class importlib.machinery.AppleFrameworkLoader(name, path)

フレームワーク形式の拡張モジュールを読み込み事ができる、特殊な importlib.machinery.ExtensionFileLoader です。

iOS App Store との互換性のため、 iOS アプリの すべての バイナリモジュールは、パッケージ化されたアプリの Frameworks フォルダーに保存された、適切なメタデータ付きのフレームワークにある動的ライブラリである必要があります。フレームワークごとにバイナリは一つだけで、 Frameworks フォルダーの外に実行可能バイナリデータを設置することはできません。

この要件に対応するため、iOS で実行する拡張モジュールのバイナリは、sys.path 上の .so ファイルでは なく、個別の独立したフレームワークとしてパッケージ化されます。 これらのフレームワークを検出するため、このローダーは .fwork 拡張子に対して登録されます。 .fwork ファイルは、sys.path 上のバイナリの元の場所に置くプレースホルダーとして機能します。 .fwork ファイルには、Frameworks フォルダ内にある実際のバイナリのパスを、アプリバンドルからの相対パスで記録します。 フレームワークにまとめたバイナリから元の場所を解決できるよう、フレームワークには .origin ファイルを含め、そこに .fwork ファイルの場所をアプリバンドルからの相対パスで記録する必要があります。

例えば、from foo.bar import _whiz をインポートする場合を考えてみましょう。 _whiz がバイナリモジュール sources/foo/bar/_whiz.abi3.so で実装されており、 sources のアプリケーションバンドルからの相対パスが sys.path に登録されています。このモジュールは Frameworks/foo.bar._whiz.framework/foo.bar._whiz (フレームワーク名はモジュールの完全なインポートパスから命名されています)として、 Info.plist ファイルをバイナリをフレームワークとして識別する .framework ディレクトリ内に設置して配布しなければなりません。 foo.bar._whiz モジュールは、元の場所で、 Frameworks/foo.bar._whiz/foo.bar._whiz のパスを含む sources/foo/bar/_whiz.abi3.fwork マーカーファイルに記述されます。 また、フレームワークは、 .fwork へのパスを含む Frameworks/foo.bar._whiz.framework/foo.bar._whiz.origin も含まなければなりません。

このローダーでモジュールをロードすると、モジュールの __file__ は .fwork ファイルの場所になります。 そのため、モジュールの __file__ を基点としてファイルシステムをたどるコードを使えます。 ただし、スペックの origin は .framework フォルダ内の 実際の バイナリの場所を指します。

PYTHONPATH 内のどこにある .so ファイルも、Frameworks フォルダ内のフレームワークに変換し、.fwork と .origin ファイルを作成する責任は、アプリをビルドする Xcode プロジェクトにあります。 変換には、モジュールファイルの拡張子の除去、フレームワークのメタデータの追加、生成されたフレームワークへの署名も含まれます。 通常は Xcode プロジェクトのビルドステップで行います。 このビルドステップの作成方法は iOS のドキュメントを参照してください。

Added in version 3.13.

name

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

path

拡張モジュールの .fwork ファイルへのパス。

importlib.util -- インポーター向けのユーティリティ

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


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

importlib.util.MAGIC_NUMBER

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

Added in version 3.4.

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

ソースの path に対応するバイトコンパイル済みファイルへの、PEP 3147/PEP 488 に従うパスを返します。 例えば、path が /foo/bar/baz.py の場合、Python 3.2 での戻り値は /foo/bar/__pycache__/baz.cpython-32.pyc です。 cpython-32 という文字列は現在のマジックタグに由来します (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 が上げられます。

Added in version 3.4.

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

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

バージョン 3.15 で変更: debug_override 引数を削除しました。

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 を送出します。

Added in version 3.4.

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

importlib.util.decode_source(source_bytes)

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

Added in version 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 が送出されます。

Added in version 3.3.

バージョン 3.9 で変更: インポート文との一貫性を高めるため、不正な相対インポートに対して ValueError ではなく ImportError を送出するようになりました。

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

モジュールの スペック を検索します。 必要に応じて、指定した package 名を基準にした相対名を使えます。 モジュールが sys.modules にあれば、sys.modules[name].__spec__ を返します (ただし、スペックが None か未設定の場合は ValueError を送出します)。 それ以外の場合は sys.meta_path を使って検索します。 スペックが見つからなければ None を返します。

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

name と package は importlib.import_module() と同じように働きます。

Added in version 3.4.

バージョン 3.7 で変更: package が実際にはパッケージでない (__path__ 属性がない) 場合、AttributeError ではなく ModuleNotFoundError を送出するようになりました。

importlib.util.module_from_spec(spec)

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

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

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

Added in version 3.5.

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

ローダーに基づいて ModuleSpec インスタンスを作成するファクトリー関数です。 引数は ModuleSpec と同じ意味です。 InspectLoader.is_package などの利用可能な ローダー API を使い、スペックに不足している情報を補います。

Added in version 3.4.

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

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

Added in version 3.4.

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

importlib.util.source_hash(source_bytes)

source_bytes のハッシュをバイト列として返します。 ハッシュベースの .pyc ファイルは、対応するソースファイルの内容の source_hash() をヘッダに埋め込みます。

Added in version 3.7.

importlib.util._incompatible_extension_module_restrictions(*, disable_check)

拡張モジュールの互換性チェックを一時的に省略できるコンテキストマネージャです。 デフォルトではチェックが有効で、単一フェーズの初期化を使うモジュールをサブインタープリタにインポートすると失敗します。 また、複数フェーズの初期化を使うモジュールでも、インタープリタごとの GIL を明示的にサポートしていなければ、独自の GIL を持つインタープリタへのインポートは失敗します。

この関数は特殊なケースに対応するためのものであり、そのケースも将来なくなる可能性があります。 探していた機能とは違う可能性が高いことに注意してください。

複数フェーズの初期化 (PEP 489) の基本インターフェースを実装し、複数インタープリタ (またはインタープリタごとの GIL) のサポートを偽って申告することでも、この関数と同じ効果を得られます。

警告

この関数でチェックを無効にすると、予期しない動作やクラッシュさえ引き起こす場合があります。 拡張モジュールの開発中に限って使ってください。

Added in version 3.12.

class importlib.util.LazyLoader(loader)

モジュールの属性がアクセスされるまで、そのモジュールのローダーの実行を遅延するクラスです。

このクラスは、モジュールに使う型を制御する必要があるため、exec_module() を定義したローダーで のみ 動作します。 同じ理由で、ローダーの create_module() メソッドは、None か、__class__ 属性を変更でき、かつ スロット を使わない型のオブジェクトを返す必要があります。 また、sys.modules に置いたオブジェクトを別のオブジェクトに差し替えるモジュールでは動作しません。 インタープリタ全体のモジュールへの参照を安全かつ正しく置き換える方法がないためです。 このような差し替えを検出すると ValueError を送出します。

注釈

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

Added in version 3.5.

バージョン 3.6 で変更: create_module() を呼び出すようになり、importlib.machinery.BuiltinImporter と 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() を使ってください。

name がサブモジュールを指す (ドットを含む) 場合、importlib.util.find_spec() は親モジュールをインポートします。

import importlib.util
import sys

# 説明のための例。
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:
    # 実際にインポートする場合...
    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")

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

この方法は注意して使ってください。 sys.path を検索する代わりにファイルパスを直接指定し、インポート文に近い動作をするものです。 まずは、正式なモジュールが必要なら sys.path を変更する、Python ファイルを実行した結果のグローバル名前空間でよければ runpy.run_path() を使うなど、別の方法を検討してください。

パスから Python ソースファイルを直接インポートするには、次のようにします。

import importlib.util
import sys


def import_from_path(module_name, file_path):
    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)
    return module


# 説明のための例にすぎない (`json` を選んだことに特別な意味はない)。
import json
file_path = json.__file__
module_name = json.__name__

# `import json` と同様の結果。
json = import_from_path(module_name, file_path)

遅延インポートの実装

以下の例は遅延インポートを実装する方法を示します。

>>> 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 は実際のモジュールオブジェクトだが、
>>> #まだメモリにロードされていない。
>>> lazy_typing.TYPE_CHECKING
False

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

インポートを大幅にカスタマイズする場合、通常は インポーター を実装します。 そのためには、ファインダー と ローダー の両方を扱います。 ファインダーには メタパスファインダー と パスエントリファインダー の 2 種類があり、必要に応じて選べます。 前者は sys.meta_path に登録するものです。 後者は sys.path_hooks にある パスエントリフック が sys.path の各要素に対して処理し、必要に応じて作成するものです。 この例では、独自のインポーターをインポート時に使わせるために登録する方法を示します (インポーター自体の作成方法は、このパッケージで定義された適切なクラスのドキュメントを読んでください)。

import importlib.machinery
import sys

# 説明のための例。
SpamMetaPathFinder = importlib.machinery.PathFinder
SpamPathEntryFinder = importlib.machinery.FileFinder
loader_details = (importlib.machinery.SourceFileLoader,
                  importlib.machinery.SOURCE_SUFFIXES)

# メタパスファインダーを設定する。
# 優先順位に応じて、リスト内の適切な位置にファインダーを登録する。
sys.meta_path.append(SpamMetaPathFinder)

# パスエントリファインダーを設定する。
# 優先順位に応じて、リスト内の適切な位置にパスフックを登録する。
sys.path_hooks.append(SpamPathEntryFinder.path_hook(loader_details))

importlib.import_module() に近い実装

インポート自体が Python コードで実装されているため、インポート機構の大部分を importlib を通じて公開できます。 以下では importlib.import_module() に近い実装を示し、importlib が公開するさまざまな API の使い方を説明します。

import importlib.util
import sys

def import_module(name, package=None):
    """インポートに近い動作をする実装。"""
    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