我有以下代码可以动态加载模块:
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, "."]
哦,是的,原因是我还想支持导入不是正确的程序包/模块的模块,而只是支持某些可以在解释器中使用的脚本。
可复制的代码:
import b
print("hi")
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
在所有脚本中手动放置内容。
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
您在这里使用动态导入并没有关系;同样的问题也适用于任何假设当前目录位于路径中的代码。这些脚本负责确保当前目录位于路径本身上。
而不是使用'.'
(当前工作目录),而是使用__file__
全局将目录添加到路径:
import os.path
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
您可以通过添加重试您的动态导入os.path.dirname(absolute_path)
到sys.path
当你有一个ImportError
(也许检测,这是一个短暂的导入失败),但是这是一个巨大的飞跃,使你不能缺少的依赖,并作出有关的假设一个模块之间的区别sys.path
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句