36.2. imp
--- import 内部へのアクセス¶
ソースコード: Lib/imp.py
このモジュールは 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要素のタプルで、見つかったモジュールの種類を説明しています。モジュールがファイルとして存在していなければ、返された file は
None
で、 pathname は空文字列、 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 で非推奨: Use
importlib.util.find_spec()
instead unless Python 3.3 compatibility is required, in which case useimportlib.find_loader()
.
-
imp.
load_module
(name, file, pathname, description)¶ find_module()
を使って(あるいは、互換性のある結果を作り出す検索を行って)以前見つけたモジュールをロードします。この関数はモジュールをインポートするという以上のことを行います: モジュールが既にインポートされているならば、リロードします! name 引数は(これがパッケージのサブモジュールならばパッケージ名を含む)完全なモジュール名を示します。 file 引数はオープンしたファイルで、 pathname は対応するファイル名です。モジュールがパッケージであるかファイルからロードされようとしていないとき、これらはそれぞれNone
と''
であっても構いません。get_suffixes()
が返すように description 引数はタプルで、どの種類のモジュールがロードされなければならないかを説明するものです。ロードが成功したならば、戻り値はモジュールオブジェクトです。そうでなければ、例外(たいていは
ImportError
)が発生します。重要: file 引数が
None
でなければ、例外が発生した場合でも呼び出し側にはそれを閉じる責任があります。これを行うには、try
...finally
文を使うことが最も良いです。バージョン 3.3 で非推奨: If previously used in conjunction with
imp.find_module()
then consider usingimportlib.import_module()
, otherwise use the loader returned by the replacement you chose forimp.find_module()
. If you calledimp.load_module()
and related functions directly then use the classes inimportlib.machinery
, e.g.importlib.machinery.SourceFileLoader(name, path).load_module()
.
-
imp.
new_module
(name)¶ name という名前の新しい空モジュールオブジェクトを返します。このオブジェクトは
sys.modules
に挿入され ません 。バージョン 3.4 で非推奨: Use
types.ModuleType
instead.
-
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()
を使用してください。- Python モジュールのコードは再コンパイルされ、モジュールレベルのコードは再度実行されます。モジュールの辞書中にある、何らかの名前に結び付けられたオブジェクトを新たに定義します。拡張モジュール中の
以下は、 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
に挿入してください。-
36.2.1. 使用例¶
次の関数は 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()