# `imp` --- import 内部へのアクセス

ソースコード: Lib/imp.py

バージョン 3.4 で非推奨、バージョン 3.12 で削除予定: `imp` モジュールは `importlib` を後継として非推奨にされました。

このモジュールは `import` 文を実装するために使われているメカニズムへのインターフェイスを提供します。次の定数と関数が定義されています:

imp.get_magic()

  バイトコンパイルされたコードファイル(`.pyc` ファイル)を認識するために使われるマジック文字列値を返します。 (この値は Python の各バージョンで異なります。)

  バージョン 3.4 で非推奨: 代わりに `importlib.util.MAGIC_NUMBER` を使用してください。

imp.get_suffixes()

  3要素のタプルのリストを返します。それぞれのタプルは特定の種類のモジュールを説明しています。各タプルは `(suffix, mode, type)` という形式です。ここで、 suffix は探すファイル名を作るためにモジュール名に追加する文字列です。そのファイルをオープンするために、 mode は組み込み `open()` 関数へ渡されるモード文字列です (これはテキストファイル対しては `'r'` 、バイナリファイルに対しては `'rb'` となります)。 type はファイル型で、以下で説明する値 `PY_SOURCE`, `PY_COMPILED` あるいは、 `C_EXTENSION` の一つを取ります。

  バージョン 3.3 で非推奨: 代わりに `importlib.machinery` で定義された定数を使ってください。

imp.find_module(name[, path])

  モジュール name を見つけようとします。 path が省略されるか `None` ならば、 `sys.path` によって与えられるディレクトリ名のリストが検索されます。しかし、最初にいくつか特別な場所を検索します。まず、所定の名前をもつ組み込みモジュール(`C_BUILTIN`)を見つけようとします。それから、フリーズされたモジュール(`PY_FROZEN`)、そしていくつかのシステムでは他の場所が同様に検索されます (Windowsでは、特定のファイルを指すレジストリの中を見ます)。

  それ以外の場合、 path はディレクトリ名のリストでなければなりません。上の `get_suffixes()` が返す拡張子のいずれかを伴ったファイルを各ディレクトリの中で検索します。リスト内の有効でない名前は黙って無視されます(しかし、すべてのリスト項目は文字列でなければなりません)。

  検索が成功すれば、戻り値は3要素のタプル `(file, pathname, description)` です:

  file は先頭に位置合わせされたオープン ファイルオブジェクト で、 pathname は見つかったファイルのパス名です。そして、 description は `get_suffixes()` が返すリストに含まれているような3要素のタプルで、見つかったモジュールの種類を説明しています。

  モジュールが組み込みモジュールか frozen なモジュールの場合、 file と pathname のどちらも `None` になり、 description タプルの要素の接尾辞 (拡張子) とモードは空文字列になります。モジュール型は上の括弧の中に示されます。 検索に失敗した場合は、 `ImportError` が発生します。 他の例外は引数または環境に問題があることを示しています。

  モジュールがパッケージならば、 file は `None` で、 pathname はパッケージのパスで description タプルの最後の項目は `PKG_DIRECTORY` です。

  この関数は階層的なモジュール名(ドットを含む名前)を扱いません。 P.M 、すなわちパッケージ P のサブモジュール M を見つけるためには、まず `find_module()` と `load_module()` を使用してパッケージ P を見つけてロードして、次に `P.__path__` を path 引数にして `find_module()` を呼び出してください。もし P 自体がドット付きの名前を持つ場合、このレシピを再帰的に適用してください。

  バージョン 3.3 で非推奨: Python 3.3 との互換性が不要であれば、`importlib.util.find_spec()` を使用してください, 互換性が必要な場合は `importlib.find_loader()` を使用してください。前者の使用例は、`importlib` ドキュメントの 使用例 セクションを参照してください。

imp.load_module(name, file, pathname, description)

  `find_module()` を使って(あるいは、互換性のある結果を作り出す検索を行って)以前見つけたモジュールをロードします。この関数はモジュールをインポートするという以上のことを行います: モジュールが既にインポートされているならば、リロードします! name 引数は(これがパッケージのサブモジュールならばパッケージ名を含む)完全なモジュール名を示します。 file 引数はオープンしたファイルで、 pathname は対応するファイル名です。モジュールがパッケージであるかファイルからロードされようとしていないとき、これらはそれぞれ `None` と `''` であっても構いません。 `get_suffixes()` が返すように description 引数はタプルで、どの種類のモジュールがロードされなければならないかを説明するものです。

  ロードが成功したならば、戻り値はモジュールオブジェクトです。そうでなければ、例外(たいていは `ImportError`)が発生します。

  重要: file 引数が `None` でなければ、例外が発生した場合でも呼び出し側にはそれを閉じる責任があります。これを行うには、 `try` ... `finally` 文を使うことが最も良いです。

  バージョン 3.3 で非推奨: もし以前は `imp.find_module()` と一緒に使っていたのなら、 `importlib.import_module()` を使うことを検討してください。 そうでなければ、 `imp.find_module()` に対して選択した代替手段によって返されるローダーを使用してください。 もし `imp.load_module()` とそれに関連する関数を path 引数付きで直接呼んでいたのなら、 `importlib.util.spec_from_file_location()` と `importlib.util.module_from_spec()` を組み合わせて使ってください。 様々な手法の詳細については `importlib` ドキュメントの 使用例 節を参照してください。

imp.new_module(name)

  name という名前の新しい空モジュールオブジェクトを返します。このオブジェクトは `sys.modules` に挿入され ません 。

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

imp.reload(module)

  すでにインポートされた module を再解釈し、再初期化します。引数はモジュールオブジェクトでなければならないので、予めインポートに成功していなければなりません。この関数はモジュールのソースコードファイルを外部エディタで編集して、Python インタプリタから離れることなく新しいバージョンを試したい際に有効です。戻り値は (module 引数と同じ) モジュールオブジェクトです。

  `reload(module)` を実行すると、以下の処理が行われます:

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

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

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

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

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

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

      try:
          cache
      except NameError:
          cache = {}

  ビルトインのモジュールや動的にロードされたモジュールをリロードすることは、 `sys`, `__main__`, `builtins` を除いて一般にはそれほど有用ではありませんが、合法です。しかし、多くの場合、拡張モジュールは二度以上初期化されるようには作られておらず、リロードされた時に無作為な方法で失敗するかもしれません。

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

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

  バージョン 3.3 で変更: リロードされるモジュール上で、`__name__` だけでなく `__name__` と `__loader__` の両方が定義されていることに依存します。

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

以下は、 PEP 3147 のバイトコンパイルされたファイルパスを扱うために便利な関数です。

バージョン 3.2 で追加.

imp.cache_from_source(path, debug_override=None)

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

  path は存在している必要はありません。

  バージョン 3.3 で変更: `sys.implementation.cache_tag` が `None` の場合、 `NotImplementedError` が上げられます。

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

  バージョン 3.5 で変更: debug_override 引数は `.pyo` ファイルを作成することはもうありません。

imp.source_from_cache(path)

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

  バージョン 3.3 で変更: `sys.implementation.cache_tag` が定義されていない場合、 `NotImplementedError` が上げられます。

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

imp.get_tag()

  `get_magic()` によって返されるのと同じ、このバージョンの Python のマジックナンバーと一致する PEP 3147 のマジックタグ文字列を返します。

  バージョン 3.4 で非推奨: Python 3.3 からは `sys.implementation.cache_tag` を直接使ってください。

以下の関数はインポートシステムの内部ロックメカニズムとのやりとりをサポートします。インポートのロックセマンティクスはリリース毎に変わる可能性のある実装詳細です。ただし、Python は循環インポートがデッドロックなしで動作することを保証しています。

imp.lock_held()

  現在グローバルなインポートロックが保持されている場合 `True` を返し、そうでなければ `False` を返します。スレッドのないプラットフォームでは常に `False` を返します。

  スレッドを持つプラットフォームでは、まずインポートを実行するスレッドがグローバルなインポートロックを保持し、次にインポートの残りの部分を実行するためにモジュール単位のロックをセットアップします。これは、他のスレッドが同じモジュールをインポートするのをオリジナルのインポートが完了するまでブロックして、他のスレッドがオリジナルのスレッドによって構築された不完全なモジュールオブジェクトを見てしまわないようにします。循環インポートに対しては例外が発生します。これは、そのようなモジュールを構築するためには、どこかの時点で不完全なモジュールオブジェクトを露出しなければならないためです。

  バージョン 3.3 で変更: ロックスキームは、大部分がモジュール毎のロックに変わりました。グローバルなインポートロックは、モジュール毎のロックを初期化するようないくつかのクリティカルタスクのために維持されます。

  バージョン 3.4 で非推奨.

imp.acquire_lock()

  現在のスレッドに対するインタープリタのグローバルなインポートロックを獲得します。このロックは、モジュールをインポートする際にスレッドセーフ性を保証するために、インポートフックによって使用されるべきです。

  一旦スレッドがインポートロックを取得したら、その同じスレッドはブロックされることなくそのロックを再度取得できます。スレッドはロックを取得するのと同じだけ解放しなければなりません。

  スレッドのないプラットホームではこの関数は何もしません。

  バージョン 3.3 で変更: ロックスキームは、大部分がモジュール毎のロックに変わりました。グローバルなインポートロックは、モジュール毎のロックを初期化するようないくつかのクリティカルタスクのために維持されます。

  バージョン 3.4 で非推奨.

imp.release_lock()

  インタープリタのグローバルなインポートロックを解放します。スレッドのないプラットフォームでは何もしません。

  バージョン 3.3 で変更: ロックスキームは、大部分がモジュール毎のロックに変わりました。グローバルなインポートロックは、モジュール毎のロックを初期化するようないくつかのクリティカルタスクのために維持されます。

  バージョン 3.4 で非推奨.

整数値をもつ次の定数はこのモジュールの中で定義されており、 `find_module()` の検索結果を表すために使われます。

imp.PY_SOURCE

  ソースファイルとしてモジュールが発見された。

  バージョン 3.3 で非推奨.

imp.PY_COMPILED

  コンパイルされたコードオブジェクトファイルとしてモジュールが発見された。

  バージョン 3.3 で非推奨.

imp.C_EXTENSION

  動的にロード可能な共有ライブラリとしてモジュールが発見された。

  バージョン 3.3 で非推奨.

imp.PKG_DIRECTORY

  パッケージディレクトリとしてモジュールが発見された。

  バージョン 3.3 で非推奨.

imp.C_BUILTIN

  モジュールが組み込みモジュールとして発見された。

  バージョン 3.3 で非推奨.

imp.PY_FROZEN

  モジュールが frozen モジュールとして発見された。

  バージョン 3.3 で非推奨.

class imp.NullImporter(path_string)

  `NullImporter` 型は PEP 302 インポートフックで、何もモジュールが見つからなかったときの非ディレクトリパス文字列を処理します。この型を既存のディレクトリや空文字列に対してコールすると `ImportError` が発生します。それ以外の場合は `NullImporter` のインスタンスが返されます。

  インスタンスはたった一つのメソッドを持ちます:

  find_module(fullname[, path])

    このメソッドは常に `None` を返し、要求されたモジュールが見つからなかったことを表します。

  バージョン 3.3 で変更: `NullImporter` のインスタンスの代わりに `None` が `sys.path_importer_cache` に挿入されます。

  バージョン 3.4 で非推奨: 代わりに `None` を `sys.path_importer_cache` に挿入してください。

## 使用例

次の関数は Python 1.4 までの標準 import 文(階層的なモジュール名がない)をエミュレートします。 (この 実装 はそのバージョンでは動作しないでしょう。なぜなら、 `find_module()` は拡張されており、また `load_module()` が 1.4 で追加されているからです。)

    import imp
    import sys

    def __import__(name, globals=None, locals=None, fromlist=None):
        # Fast path: see if the module has already been imported.
        try:
            return sys.modules[name]
        except KeyError:
            pass

        # If any of the following calls raises an exception,
        # there's a problem we can't handle -- let the caller handle it.

        fp, pathname, description = imp.find_module(name)

        try:
            return imp.load_module(name, fp, pathname, description)
        finally:
            # Since we may exit via an exception, close fp explicitly.
            if fp:
                fp.close()