Python のモジュールは通常であれば import 文を使ってあらかじめ静的にロードする。 では、プログラムの中で動的にロードしたい場合にはどうしたらいいのか?というのが今回の話。 結論から先に言うと今は標準ライブラリの importlib を使うのが推奨される方法のようだ。
使った環境は次の通り。
$ python --version Python 3.5.1 $ sw_vers ProductName: Mac OS X ProductVersion: 10.11.3 BuildVersion: 15D21
下準備
まずは適当に Python のモジュールを作っておく。 Python のモジュールというのは単なる Python ファイルのことだ。
$ cat << 'EOF' > helloworld.py #!/usr/bin/env python # -*- coding: utf-8 -*- def greet(): print('Hello, World!') EOF
動的にロードしてみる
ファイル名が helloworld.py であれば Python からは helloworld モジュールとしてインポートできる。 まずは通常通り import 文を使って helloworld モジュールをロードしてみよう。 helloworld.py があるのと同じディレクトリで Python の REPL を起動して次を実行する。
$ python
>>> import helloworld
>>> helloworld.greet()
Hello, World!
ちゃんとモジュールがロードできていることが分かる。
次に importlib を使ってロードする方法を試してみよう。 importlib を使ってモジュールをロードするには import_module() 関数を使う。 この関数にはモジュール名を文字列で指定すると返り値としてモジュールが得られる。
>>> import importlib >>> module = importlib.import_module('helloworld') >>> module.greet() Hello, World! >>> module.__name__ 'helloworld'
ばっちりだ。
名前を指定してロードしたい
先ほどの import_module() 関数ではモジュール名の指定ができなかった。 モジュール名を指定してロードしたい場合には importlib の中でもより低レベルな API を使う必要がある。 具体的には importlib.machinery の SourceFileLoader を使う。 このクラスはモジュール名と、その名前で読み込む Python ファイルを指定してインスタンス化することになっている。 得られたインスタンスの load_module() メソッドを呼び出すことでモジュールが手に入るという寸法だ。
>>> from importlib import machinery >>> loader = machinery.SourceFileLoader('mymodule', 'helloworld.py') >>> module = loader.load_module() >>> module.greet() Hello, World! >>> module.__name__ 'mymodule'
指定した通り helloworld.py が mymodule という名前のモジュールとしてロードされていることがわかる。
注意点
標準ライブラリの importlib は Python 3.3 から導入されたモジュールだ。 以前は同様の機能を提供する標準ライブラリとして imp があったものの、これは 3.x では非推奨となっている。 Python 2.7 にも一応は importlib が存在するものの、限定的な機能を提供するサブセットになっている。 もし Python 2.x でもフルセットの importlib が使いたいときはバックポート版を PyPI からインストールする必要がある。
$ pip install importlib
めでたしめでたし。
スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログを見る