imp – モジュールのインポート構造に対するインタフェース¶
目的: | imp モジュールは Python の import 文の実装を公開する |
---|---|
利用できるバージョン: | 2.2.1 以上 |
imp モジュールにはパッケージやモジュールでコードを読み込む Python のインポート構造における下位実装を公開する機能があります。それは動的にインポートしたモジュールへの1つのアクセスポイントです。そして、コード(例えば、アプリケーションのプラグイン、又は拡張機能)を書くときにインポートする必要のあるモジュール名を知らないときに役立ちます。
example パッケージ¶
次のサンプルは __init__.py で “example” というパッケージを使用します。
print 'Importing example package'
そして、submodule というモジュールも含みます。
print 'Importing submodule'
パッケージ又はモジュールがインポートされたときに出力する print 文のテキストに注目してください。
モジュールタイプ¶
Python はモジュールの複数のスタイルをサポートします。モジュールをオープンして名前空間へそのモジュールを追加するときに、モジュールタイプそれぞれの要素独自の操作を必要とします。サポートされているタイプとそのパラメータは get_suffixes() 関数で表示することができます。
import imp
module_types = { imp.PY_SOURCE: 'source',
imp.PY_COMPILED: 'compiled',
imp.C_EXTENSION: 'extension',
imp.PY_RESOURCE: 'resource',
imp.PKG_DIRECTORY: 'package',
}
def main():
fmt = '%10s %10s %10s'
print fmt % ('Extension', 'Mode', 'Type')
print '-' * 32
for extension, mode, module_type in imp.get_suffixes():
print fmt % (extension, mode, module_types[module_type])
if __name__ == '__main__':
main()
get_suffixes() はファイル拡張子、ファイルを開くために使用するモード、そしてモジュールで定義された定数のタイプコードを含むタプルのリストを返します。このテーブルは不完全です。というのは、インポート可能なモジュール又はパッケージのタイプは1つのファイルに対応しないからです。
$ python imp_get_suffixes.py
Extension Mode Type
--------------------------------
.so rb extension
module.so rb extension
.py U source
.pyc rb compiled
モジュールを見つける¶
モジュールを読み込むための最初のステップはそのモジュールを見つけることです。 find_module() はインポートされた検索パスを精査して、与えられた名前からパッケージ又はモジュールを探します。 find_module() は(そのタイプが適切なら)ファイルハンドラ、モジュールを見つけたファイル名、そして “description”( get_suffixes() が返すタプル) を返します。
import imp
from imp_get_suffixes import module_types
print 'Package:'
f, filename, description = imp.find_module('example')
print module_types[description[2]], filename
print
print 'Sub-module:'
f, filename, description = imp.find_module('submodule', [filename])
print module_types[description[2]], filename
if f: f.close()
find_module() はドットを含むパッケージ名(“example.submodule”)には注意しません。そのため、呼び出し側はネストされたモジュールの正しいパスを渡すことに注意する必要があります。パッケージからサブモジュールをインポートする場合、探しているモジュールを配置するために find_module() にパッケージのディレクトリパスを渡す必要があります。
$ python imp_find_module.py
Package:
package /Users/dhellmann/Devel/pymotw-ja/t2y/PyMOTW/imp/example
Sub-module:
source /Users/dhellmann/Devel/pymotw-ja/t2y/PyMOTW/imp/example/submodule.py
もし find_module() がそのモジュールを配置できなかったら ImportError を発生させます。
import imp
try:
imp.find_module('no_such_module')
except ImportError, err:
print 'ImportError:', err
$ python imp_find_module_error.py
ImportError: No module named no_such_module
モジュールを読み込む¶
モジュールを見つけたら、実際にそのモジュールをインポートするために load_module() を使用してください。 load_module() は完全にドットで区切られたパスのモジュール名と find_module() が返す値(ファイルハンドラ、ファイル名、説明のタプル)を引数に取ります。
import imp
f, filename, description = imp.find_module('example')
example_package = imp.load_module('example', f, filename, description)
print 'Package:', example_package
f, filename, description = imp.find_module('submodule',
example_package.__path__)
try:
submodule = imp.load_module('example.module', f, filename, description)
print 'Sub-module:', submodule
finally:
f.close()
load_module() は与えられた名前でモジュールのコードを読み込んで新たなモジュールオブジェクトを作成します。そして sys.modules にモジュールを追加します。
$ python imp_load_module.py
Importing example package
Package: <module 'example' from '/Users/dhellmann/Documents/PyMOTW/trunk/PyMOTW/imp/example/__init__.py'>
Importing submodule
Sub-module: <module 'example.module' from '/Users/dhellmann/Documents/PyMOTW/trunk/PyMOTW/imp/example/submodule.py'>
既にインポートされているモジュールに対して load_module() を呼び出すと、既存のモジュールオブジェクトに reload() を呼び出すような結果になります。
import imp
import sys
for i in range(2):
print i,
try:
m = sys.modules['example']
except KeyError:
print '(not in sys.modules)',
else:
print '(have in sys.modules)',
f, filename, description = imp.find_module('example')
example_package = imp.load_module('example', f, filename, description)
新たなモジュールを作成する代わりに、既存モジュールのコンテンツを単純に置き換えます。
$ python imp_load_module_reload.py
0 (not in sys.modules) Importing example package
1 (have in sys.modules) Importing example package
See also
- imp
- 本モジュールの標準ライブラリドキュメント
- Modules and Imports
- インポートフック、モジュールのパス検索、その他の関連する仕組み
- inspect
- モジュールプログラムから情報を読み込む
- PEP 302
- 新たなインポートフック
- PEP 369
- インポートフックの投稿