代码之家  ›  专栏  ›  技术社区  ›  N Chauhan Nathan Hinchey

重新加载不同目录中以编程方式导入的文件时找不到ModuleSpec

  •  0
  • N Chauhan Nathan Hinchey  · 技术社区  · 6 年前

    当我在CLI中实现一个重新加载函数时,我偶然发现了一个我似乎无法解决的奇怪错误。要重新创建它,首先,在CWD的另一个目录中创建一个虚拟文件。对于这个例子,我称之为 test.py

    使用配方 here ,但请确保CWD是单独的,并且 使用CWD作为“阀杆”无法到达。

    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)
    

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

    0 回复  |  直到 6 年前
        1
  •  0
  •   stevecu    6 年前

    使用最新版本的python(>=3.4),可以添加 MetaPathFinder sys.meta_path 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 是一些dict将模块名称映射到位置。

    有关详细信息: https://docs.python.org/3/library/importlib.html#setting-up-an-importer (实际上,这就在你找到配方的地方下面)