Pythonはインタプリタなので、文字列から動的なimportが可能である。
Pythonのコードの中で、NewModule.py
を作って、それを読み込んでみよう。
NewModule.py
に書くテキスト
print(0) a = 10 + 0
Pythonコード。import importlib
が重要。
module_name = "NewModule" import importlib i=0 with open(f"{module_name}.py","w") as f: f.write(f"print({i})\n") f.write(f"a = 10 + {i}\n") mod = importlib.import_module(module_name) print(f"{module_name}.a = {mod.a}")
出力
0 NewModule.a = 10
では、NewModule.py
をPython内で更新した場合はどうなるか?
module_name = "NewModule" import time import importlib for i in range(10): with open(f"{module_name}.py","w") as f: f.write(f"print({i})\n") f.write(f"a = 10 + {i}\n") i+=1 #キャッシュが効いて更新したファイルを読み込めないことがあるので1秒待つ time.sleep(1) mod = importlib.import_module(module_name) print(f"{module_name}.a = {mod.a}")
出力
0 NewModule.a = 10 NewModule.a = 10 NewModule.a = 10 NewModule.a = 10 NewModule.a = 10 NewModule.a = 10 NewModule.a = 10 NewModule.a = 10 NewModule.a = 10 NewModule.a = 10
Pythonユーザーならご存知だろうが、再importしても、モジュールは読み込まれない。なので、モジュールのPythonファイルを書き換えても、カーネル内のモジュールは更新はされない。
そこで、importlib.reload
を使って、再import(リロード)させる。
module_name = "NewModule" import time import sys import importlib for i in range(10): with open(f"{module_name}.py","w") as f: f.write(f"print({i})\n") f.write(f"a = 10 + {i}\n") i+=1 #キャッシュが効いて更新したファイルを読み込めないことがあるので1秒待つ time.sleep(1) if module_name in sys.modules: print("reload") importlib.reload(importlib.import_module(module_name)) mod = importlib.import_module(module_name) print(f"{module_name}.a = {mod.a}")
出力
0 NewModule.a = 10 reload 1 NewModule.a = 11 reload 2 NewModule.a = 12 reload 3 NewModule.a = 13 reload 4 NewModule.a = 14 以下略
以前のカーネルが再利用した場合は、最初にreloadが出る。
これで、Python内で動的にモジュールを作成、import、再import(リロード)ができた。
最後に、モジュールを再読み込みするだけのシンプルコード
import sys import importlib module_name = "global_a" if module_name in sys.modules: print("reload",module_name) importlib.reload(importlib.import_module(module_name)) mod = importlib.import_module(module_name) from global_a import *