我正在编写一个支持插件架构的 Flask 应用程序。每个插件都位于一个单独的文件夹中,并且是一个模块,它至少具有一个类,该类是一个类的子Plugin
类。出于安全原因,我不想在烧瓶应用程序最初运行时加载所有插件。相反,用户可以从烧瓶应用程序中启用插件。一旦他这样做了,我们就会在数据库中存储一个备忘录,将应用程序列入白名单以供加载。但是,我们仍然必须记住哪些插件被禁用并证明了这些插件的视图。我通过为未启用且不加载任何自定义代码的插件创建一个虚拟类来做到这一点。
每个插件都有自己的蓝图。我们在加载插件时注册它。蓝图还定义了启用插件的路线。整个事情看起来像这样:
for plugin_name in os.listdir(plugin_dir):
plugin_path = os.path.join(plugin_paths, plugin_name)
module_name = "plugins.{}.__init__".format(plugin_name)
plugin_enabled = ask_db_whether_plugin_is_enabled(plugin_name)
if os.path.isdir(plugin_path) and plugin_enabled:
module = __import__(module_name)
for plugin in load_plugins_from_module(module):
app.register_blueprint(plugin.blueprint, url_prefix='/plugins')
else:
PluginCls = type(identifier, (Plugin, ), {})
disabled_plugin = PluginCls()
app.register_blueprint(disabled_plugin.blueprint, url_prefix='/plugins')
load_plugins_from_module
看起来像这样:
def load_plugins_from_module(module):
def is_plugin(c):
return inspect.isclass(c) and \
issubclass(c, Plugin) and \
c != Plugin
for name, objects in inspect.getmembers(module, lambda c: inspect.ismodule(c)):
for name, PluginCls in inspect.getmembers(objects, is_plugin):
plugin = PluginCls()
yield plugin
现在问题如下:当我将插件更改为启用时,我基本上想重新运行
module = __import__(module_name)
for plugin in load_plugins_from_module(module):
app.register_blueprint(plugin.blueprint, url_prefix='/plugins')
对于该插件的模块,使其变为活动状态并注册已在子类插件中定义的所有路由。这将引发一个AssertionError
因为我无法在运行时更改蓝图。什么是一个好的解决方法?我可以从应用程序内重新加载应用程序吗?我可以在运行时修改现有的蓝图吗?
谢谢你的帮助!