この辺を参考に、下記のようにすると、「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の構成が正解でしょう。
参考


コメント