Python动态地从模块导入类

时间:2014-12-15 14:48:44

标签: python import dynamic-loading

我正在使用具有许多子组件的API。我正在制作一个工具包来与这个API进行交互,我想这样做,以便我可以根据变量动态加载一些类,例如,加载所有具有变量api_module = True set的类。

.
├── APIModules
│   ├── ccu.py
│   ├── __init__.py
│   └── OpenAPI.py

ccu文件中的CCU类

class CCU:
    api_module = True
    actions    = ['post_new_purge','get_purge_queue','get_purge_status']

这将帮助我动态记录和扩展工具包,因为每次添加新的子组件时都会添加更多的类,而不必维护导入列表。有一个简单的方法吗?

我知道我可以使用glob获取APIModules目录中所有python文件的列表,但是我想加载并检查文件中的任何类,而不知道它们可能被称为什么。

import os
import glob
modules = glob.glob(os.path.dirname(__file__)+"/*.py")

2 个答案:

答案 0 :(得分:1)

由于你需要导入类来读取它的属性,并且你试图弄清楚你是否应该首先导入它,你在这里有一个catch 22。

这使您可以使用其他方法解析.py文件,并根据是否导入有问题的模块来决定。但是这种方法也很麻烦而且太复杂了。

我认为最简单的方法是彻底改变观点。您可以在主应用程序中只有一个活动模块列表,而不是在每个模块中都有api_module = True,并根据它来决定:

api_modules = ["module_1", "module_2", "module_3"]

这减少了维护量(您只需维护一行代码)并提供相同的灵活性。

答案 1 :(得分:1)

您可以使用元类和类注册表来跟踪添加到系统中的任何新类。

这里有一个演练,可以为您提供所需的帮助http://effbot.org/zone/metaclass-plugins.htm

它是否是一个好主意是另一个问题(我认为sqlalchemy使用这种模式作为声明基础并且它运作良好)。

# from http://effbot.org/zone/metaclass-plugins.htm
registry = [] # list of subclasses

class Plugin(object):
    class __metaclass__(type):
        def __init__(cls, name, bases, dict):
            type.__init__(name, bases, dict)
            registry.append((name, cls))

# in your plugin modules
class SpamPlugin(Plugin):
    pass

class BaconPlugin(Plugin):
    pass

# in your plugin loader
# import all plugin modules

# loop over registered plugins
for name, cls in registry:
    if cls is not Plugin:
        print name, cls
        # here you could check various attributes of the class to
        # see if it was one you wanted to use

编辑我觉得我有点误解了 - 你也不想逐个导入模块 - 但是你可以写一些东西来导入所有的api文件夹中的文件。然后,每个类都将从维护注册表的基本API类继承。如果您想使用任何内容,请转到注册表以查找您感兴趣的课程。