动态导入模块并实例化类在Python中
我的问题和这个问题有点相似,但我想更进一步。
我正在解析一个配置文件,这个文件通过名字调用了一些动作(带参数)。比如:
"on_click": "action1", "args": {"rate": 1.5}
这些动作是Python类,都是从一个基础的Action
类继承而来的,可以接受命名参数。它们存放在项目的一个名为“actions”的子目录里,文件名都以a_
开头。我希望能够通过简单地放一个新文件到这个目录里来添加新的动作,而不需要修改其他任何文件。项目的结构大致是这样的:
myapp/
actions/
__init__.py
baseaction.py
a_pretty.py
a_ugly.py
...
run.py
所有的动作类都提供了一个PerformAction()
方法和一个GetName()
方法,配置文件就是通过这个方法来引用的。在这个例子中,a_pretty.py
定义了一个叫PrettyPrinter
的类。调用PrettyPrinter
的GetName()
方法会返回“action1”。
我想把PrettyPrinter
类添加到一个字典里,用“action1”作为键,这样我就可以像下面这样创建它的新实例:
args = {'rate': the_rate}
instantiated_action = actions['action1'](**args)
instantiated_action.PerformAction()
目前,我有以下内容:
actions = [os.path.splitext(f)[0] for f in os.listdir("actions")
if f.startswith("a_") and f.endswith(".py")]
for a in actions:
try:
module = __import__("actions.%s" % a, globals(), locals(), fromlist=["*"])
# What goes here?
except ImportError:
pass
这段代码正在导入动作文件,如果我打印dir(module)
,我能看到类名;我只是还不知道接下来该怎么做(或者说这种方法是否正确...)。
1 个回答
2
如果你在你的 module
里所有的东西都是你需要创建实例的类,可以试试下面的做法:
对于每一个动作(actions)来说:
try:
module = __import__("actions.%s" % a, globals(), locals(), fromlist=["*"])
# What goes here?
# let's try to grab and instanciate objects
for item_name in dir(module):
try:
new_action = getattr(module, item_name)()
# here we have a new_action that is the instanciated class, do what you want with ;)
except:
pass
except ImportError:
pass