我正在使用具有许多子组件的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")
答案 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类继承。如果您想使用任何内容,请转到注册表以查找您感兴趣的课程。