モジュールを動的にロードする次のコードがあります。
def load_module(absolute_path):
import importlib.util
module_name, _ = os.path.splitext(os.path.split(absolute_path)[-1])
try:
py_mod = imp.load_source(module_name, absolute_path)
except ImportError:
module_root = os.path.dirname(absolute_path)
print("Could not directly load module, including dir: {}".format(module_root))
spec = importlib.util.spec_from_file_location(
module_name, absolute_path, submodule_search_locations=[module_root, "."])
py_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(py_mod)
return py_mod
同じフォルダーにスクリプトをインポートしようとしている場合を除いて(同じ名前のパッケージの一部ではありません)、非常にうまく機能します。たとえば、スクリプトa.py
は実行していimport b
ます。エラーが発生しますImportError: No module named 'b'
(これは Python 3 で一般的です)。
しかし、私は本当にこれを解決する方法を見つけたいですか? 先頭に追加することで解決されます:
import sys
sys.path.append(".")
「a」をスクリプト化します。
私はそれが解決されることを望んでいましたが:
submodule_search_locations=[module_root, "."]
そうそう、その根拠は、適切なパッケージ/モジュールではなく、インタープリターで機能するいくつかのスクリプトであるモジュールのインポートもサポートしたいということです。
再現可能なコード:
~/example/a.py
import b
~/example/b.py
print("hi")
~/somewhere_else/main.py (a/b とは別の場所)
import sys, os, imp, importlib.util
def load_module(absolute_path) ...
load_module(sys.argv[1])
次に、コマンド ラインで実行します。
cd ~/somewhere_else
python3.5 main.py /home/me/example/a.py
その結果、ImportError: No module named 'b'
次のコードはそれを解決しますが、もちろんsys.path
、すべてのスクリプトに手動で入れることはできません。
~/example/a.py (2)
import sys
sys.path.append(".")
import b
私がまだ考えていなかった解決策を他の人が持っていることを本当に願っています。
付録
def load_module(absolute_path):
import importlib.util
module_name, _ = os.path.splitext(os.path.split(absolute_path)[-1])
try:
py_mod = imp.load_source(module_name, absolute_path)
except ImportError as e:
if "No module named" not in e.msg:
raise e
missing_module = e.name
module_root = os.path.dirname(absolute_path)
if missing_module + ".py" not in os.listdir(module_root):
msg = "Could not find '{}' in '{}'"
raise ImportError(msg.format(missing_module, module_root))
print("Could not directly load module, including dir: {}".format(module_root))
sys.path.append(module_root)
spec = importlib.util.spec_from_file_location(module_name, absolute_path)
py_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(py_mod)
return py_mod