如何使用 importlib 动态加载 python-Files?

How to load python-Files dynamcially with importlib?

我想将 .py 文件(插件)动态加载到我的程序中。

经过一些研究,我发现通常有两种方法可以做到这一点:

1)

import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
from importlib import import_module
module = import_module("plugins." + modulename)
for name, klass in inspect.getmembers(module, inspect.isclass):
    if klass.__module__ == "plugins." + modulename:
        instance = klass()
        if isinstance(instance, IPluginTemplate):
            print("Plugin Call:", instance.do_something(x))

两种解决方案的主要区别是什么?有更好的方法吗?

在第二个例子中,你运行遍历了一个模块的所有成员,这更像是一种蛮力方法。

第一个例子(第二个也是),你找不到你想要的。如果在实例化期间未找到或出错,请测试 None。

您也可以直接从 importlib 使用 import_module。这样你就可以使用 getattr return 你想从模块中得到什么,如果抛出 AttributeError return None。

您可以使用此方法 return 模块、变量以及定义到模块中的任何内容。

import importlib

def get_from_module(module, attr_name):
    module = importlib.import_module(module)
    try:
        return getattr(module, attr_name)
    except AttributeError:
        return None

klass = get_from_module("plugins." + modulename, classname)
if klass is not None:
    instance = klass()

这个方法在我的项目 cartola 上可用,它有一些我在多个项目中使用的轻量级 util 方法。它在 pypi 上可用,请随意从配置模块导入 get_from_module 或 get_from_string。

参见:

注意:此处的引用必须是您的 PYTHONPATH 中存在的有效模块,因为您正在处理插件。我假设是这种情况。