Python中的动态模块导入

我正在编写一个以命令作为参数的Python应用程序,例如:

$ python myapp.py command1

我希望应用程序是可扩展的,也就是说,能够添加实现新命令的新模块,而不必更改主应用程序源。 树看起来像这样:

myapp/
    __init__.py
    commands/
        __init__.py
        command1.py
        command2.py
    foo.py
    bar.py

所以我希望应用程序在运行时找到可用的命令模块并执行相应的命令模块。

目前这实现了如下内容:

command = sys.argv[1]
try:
    command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
    # Display error message

command_module.run()

这工作得很好,我只是想知道是否可能有更习惯的方式来完成我们正在使用此代码做的事情。

请注意,我特别不想使用鸡蛋或扩展点。 这不是一个开源项目,我不希望有“插件”。 重点是简化主应用程序代码,并在每次添加新的命令模块时删除对其进行修改的需要。


在Python比2.7 / 3.1更早的时候,这就是你如何做到的。 对于较新的版本,请参阅importlib.import_module为2.7+和3.1+。

如果你想要,你也可以使用exec

请注意,您可以通过执行以下操作导入模块列表:

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)

从Dive Into Python中直接跳过。


Python 2.7及更高版本的推荐方法是使用importlib模块:

my_module = importlib.import_module('os.path')

如上所述,imp模块为您提供了加载功能:

imp.load_source(name, path)
imp.load_compiled(name, path)

我之前使用过这些来执行类似的操作。

在我的情况下,我用需要的定义方法定义了一个特定的类。 一旦我加载模块,我会检查该类是否在模块中,然后创建该类的一个实例,如下所示:

import imp
import os

def load_from_file(filepath):
    class_inst = None
    expected_class = 'MyClass'

    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])

    if file_ext.lower() == '.py':
        py_mod = imp.load_source(mod_name, filepath)

    elif file_ext.lower() == '.pyc':
        py_mod = imp.load_compiled(mod_name, filepath)

    if hasattr(py_mod, expected_class):
        class_inst = getattr(py_mod, expected_class)()

    return class_inst
链接地址: http://www.djcxy.com/p/38597.html

上一篇: Dynamic module import in Python

下一篇: How do I find the location of Python module sources?