python - 在不同目录中以编程方式导入的文件重新加载期间未找到 ModuleSpec

标签 python python-3.x import

在 CLI 中实现重新加载功能时,我偶然发现了这个奇怪的错误,但我似乎无法解决该错误。要重新创建此文件,首先,在与 CWD 不同的目录中创建一个虚拟文件。对于此示例,我将其称为 test.py

使用配方here ,以编程方式导入它,但确保 CWD 是独立的,并且无法使用 CWD 作为“主干”来访问 test.py 的路径。

spec = importlib.util.spec_from_file_location('test', <path>)
module = importlib.util.module_from_spec(spec)
sys.modules['test'] = module
spec.loader.exec_module(module)

尝试使用importlib.reload重新加载模块时发生错误:

>>> importlib.reload(module)

  File "C:\Program Files\Python38\lib\importlib\__init__.py", line 168, in reload
    raise ModuleNotFoundError(f"spec not found for the module {name!r}", name=name)
ModuleNotFoundError: spec not found for the module 'test'

我对 importlib.__init__.reload 进行了一些检查,它似乎调用了 _frozen_importlib._bootstrap._find_spec。引发错误的原因是未找到模块规范,但在重新加载之前属性 __spec__ 已存在。由于代码的性质,规范设置为 None:

spec = module.__spec__ = _bootstrap._find_spec(name, pkgpath, target)
if spec is None:
    raise ModuleNotFoundError(f"spec not found for the module {name!r}", name=name)

有没有办法重新加载以编程方式导入的模块?我确实需要使用文件路径保留导入的文件,因为它所属的程序允许用户编写可以放置在文件系统中任何位置的“插件”。这是我的代码的导入机制中主要发生的事情的简化版本。

最佳答案

使用合适的最新版本的 python (>=3.4),您可以将 MetaPathFinder 添加到 sys.meta_path 来告诉 python 在哪里可以找到模块规范。如果这样做,您就可以避免显式模块加载配方,并且 importlib.reload 应该可以正常工作。示例:

class ModuleFinder(importlib.abc.MetaPathFinder):

    def __init__(self, path_map:dict):
        self.path_map = path_map

    def find_spec(self, fullname, path, target=None):
        if not fullname in self.path_map:
            return None
        return importlib.util.spec_from_file_location(fullname, self.path_map[fullname])

    def find_module(self, fullname, path):
        return None # No need to implement, backward compatibility only

sys.meta_path.append(ModuleFinder(my_module_paths))

其中 my_module_paths 是将模块名称映射到位置的一些字典。

了解更多详情:https://docs.python.org/3/library/importlib.html#setting-up-an-importer (实际上,这就在您找到食谱的地方)

关于python - 在不同目录中以编程方式导入的文件重新加载期间未找到 ModuleSpec,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62052359/

相关文章:

python - 如何将压缩列表项相互相乘?

python - 如何识别字符串中的非字母

python - 如何在Python中通过一个符号链接(symbolic link)导入多个文件?

java - 如何将 '.jar'库文件导入Unity?

python - K 最短路径 Python 不工作

python - 从 CSV 文件中提取列 Python : ValueError: too many values to unpack (expected 4)

python - 根据 ndarray 中的索引设置值的通用方法?

python-3.x - ubuntu 16.04 中的 Kivy 错误

numpy - 在 binder beta 中导入 numpy 时出错

Python 随机样本异常