动态加载模块并动态调用该模块中的函数; Python 2.7

Dynamically loading module and dynamically calling function in that module; Python 2.7

我正在尝试编写 Python 2.7 代码

  1. 启动时从配置文件动态加载模块列表/数组
  2. 从那些模块中调用函数。这些功能也在配置文件中指定(可能是同一个配置文件,也可能是不同的配置文件)。

我的想法是我的代码在启动之前不知道要加载哪些模块。并且调用函数的部分直到运行时才知道要调用哪些函数以及这些函数属于哪些模块。

我没有成功。我的情况的一个简单示例是:

下面是abc.py,一个应该动态加载的模块(在我的实际应用中,我会在配置文件的列表/数组中指定几个这样的模块):

    def abc_fcn():
        print("Hello World!")

    def another_fcn():
        print("BlahBlah")

以下是应加载的 .py 代码 abc.py(我的实际代码需要从配置文件导入整个模块列表/数组)。这个 .py 文件和 abc.py 都在同一个文件夹/目录中。请注意每条语句旁边的注释。

    module_to_import = "abc"        #<- Will normally come from config file
    fcn_to_call = "abc.abc_fcn"     #<- Will normally come from config file

    __import__(module_to_import)    #<- No error

    print(help(module_to_import))   #<- Works as expected
    eval(fcn_to_call)()             #<- NameError: name 'abc' is not defined

当我将第二行更改为以下...

    fcn_to_call = "abc_fcn"

...NameError 更改为 "name 'abc_fcn' is not defined"。

我做错了什么?在此先感谢您的帮助!

您应该将 __import__ 的返回值分配给一个变量 abc 以便您可以将它实际用作一个模块。

abc = __import__(module_to_import)

__import__ 仅 returns 指定的模块,不会将其添加到全局命名空间。所以要完成你想要的,将结果保存为一个变量,然后动态检索你想要的函数。这可能看起来像

fcn_to_call = 'abc_fcn'
mod = __import__(module_to_import)
func = getattr(mod, fcn_to_call)
func()

附带说明一下,abcAbstract Base Classes builtin Python module 的名称,尽管我知道您可能只是在使用这个示例。