この辺を参考に、下記のようにすると、「E:\test_mod\addmodule.py」に置いたモジュールをインポート出来た。
#addmoduletest1.py import importlib.util MODULE_PATH = "E:\\test_mod\\addmodule.py" MODULE_NAME = "addmodule" spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH) modulevar = importlib.util.module_from_spec(spec) spec.loader.exec_module(modulevar) modulevar.printingstatement()
#E:\test_mod\addmodule.py def printingstatement(): print("From addmodule.py")
しかし、下記のように、呼び出したモジュールで相対パスで独自定義モジュールを呼び出してる場合、このモジュールは正しく読み込まれなかった。
#E:\test_mod\addmodule.py import mymod.py #自作modを相対パスでインポート def printingstatement(): print("From addmodule.py") mymod.printmymod()
#E:\test_mod\mymod.py def printmymod(): print("From printmymod.py")
Traceback (most recent call last): File "E:\テスト\addmoduletest1.py", line 11, in <module> spec.loader.exec_module(modulevar) File "<frozen importlib._bootstrap_external>", line 883, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "E:\test_mod\addmodule.py", line 2, in <module> import strcode ModuleNotFoundError: No module named 'mymod'
mymodが無いって出てくる。モジュールファイル内で相対パスで別のモジュール読み込んでても、パスの起点はそれぞれのファイルからにはならないみたい。mainで実行しているscriptが起点になるので、自作モジュールライブラリがある場合、下記のようにパスを追加して使うのが正解みたい。
#addmoduletest2.py import sys MODULE_PATH = "E:\\test_mod" sys.path.append(MODULE_PATH) import addmodule addmodule.printingstatement()
因みに、appendで追加したパスは、このスクリプト実行時のみ追加されます。
これが一番よさげ。
Cだと、#defineを#ifdefで複数回importしないようにとかやってたけど、pythonも似たような話あるんだろうか。appendは何度も実行すると、重複したパスが一杯入っちゃうし。複数回呼ぶ構成にする場合は、try import エラー出てたらexceptでappendしてからimportって感じか?
#addmoduletest3.py import sys try: import addmodule except: print("except import") MODULE_PATH = "E:\\test_mod" sys.path.append(MODULE_PATH) import addmodule addmodule.printingstatement()
しかし、いろんなファイルに、絶対パスが入るのは保守観点で良くないからこれはボツかな。自作ライブラリ使うなら、そのライブラリのパス通してから使うが基本ですね。addmoduletest2.pyの構成が正解でしょう。
参考
コメント