[python]絶対パスでのモジュール追加方法

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

参考

 

コメントを残す

メールアドレスが公開されることはありません。