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 との後方互換性のためだけに存在します。
- 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_data(path)¶
path をバイナリファイルとして読み込み、そのバイト列を返します。
- class importlib.abc.SourceLoader¶
ソース (オプションでバイトコード) ファイルのロードを実装する抽象基底クラスです。このクラスは、
ResourceLoaderとExecutionLoaderの両方を継承し、以下の実装が必要です:ExecutionLoader.get_filename()ソースファイルへのパスのみを返す必要があります。ソースなしのロードはサポートされていません。
このクラスでこれらの抽象メソッドを定義することで、バイトコードファイルを追加でサポートします。 これらのメソッドを定義しなければ (またはそのメソッドが
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¶
ファインダーが検索するパスです。
- 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¶
ソースファイルへのパスです。
- path_stats(path)¶
- set_data(path, data)¶
- class importlib.machinery.SourcelessFileLoader(fullname, path)¶
バイトコードファイル (すなわちソースコードファイルが存在しない) をインポートできる
importlib.abc.FileLoaderの具象実装です。注意として、バイトコードを直接使う (つまりソースコードファイルがない) と、そのモジュールはすべての Python 実装では使用できないし、新しいバージョンの Python ではバイトコードフォーマットが変更されていたら使用できません。
Added in version 3.3.
バージョン 3.15 で変更:
load_module()メソッドを削除しました。- name¶
ローダーが扱うモジュールの名前です。
- path¶
バイトコードファイルへのパスです。
- 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¶
拡張モジュールへのパスです。
- is_package(fullname)¶
EXTENSION_SUFFIXESに基づき、ファイルパスがパッケージの__init__モジュールを指す場合にTrueを返します。
- get_code(fullname)¶
拡張モジュールにはコードオブジェクトがないため
Noneを返します。
- get_source(fullname)¶
拡張モジュールにはソースコードがないため
Noneを返します。
- 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にしてください。 名前空間パッケージでは、後で特殊なオブジェクトが自動的に設定されます。
- cached¶
モジュールのコードをコンパイルしたファイルの名前です。 ファインダー は常にこの属性を設定する必要がありますが、コンパイル済みコードの保存が不要なモジュールでは
Noneにできます。
- parent¶
(読み取り専用) モジュールが属するパッケージの完全修飾名です (トップレベルのモジュールでは空文字列)。
module.__package__を参照してください。 モジュール自体がパッケージであれば、nameと同じです。
- 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.
利用可能な環境: iOS.
- 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