"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()
