我正在编写一个支持插件架构的 Flask 应用程序。每个插件都位于一个单独的文件夹中,并且是一个模块,该模块至少具有一个类,该类是一个子类Plugin
班级。出于安全原因,我不想在 Flask 应用程序最初运行时加载所有插件。相反,用户可以从 Flask 应用程序内启用插件。一旦他这样做了,我们就会在数据库中存储一份备忘录,将要加载的应用程序列入白名单。然而,我们仍然必须记住哪些插件被禁用以及这些插件的经过验证的视图。我通过为未启用且不加载任何自定义代码的插件创建一个虚拟类来实现此目的。
每个插件都有自己的蓝图。我们在加载插件时注册它。蓝图还定义了启用插件的路线。
整个事情看起来是这样的:
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
因为我无法在运行时更改蓝图。对此有什么好的解决方法吗?我可以从应用程序内重新加载应用程序吗?我可以在运行时修改现有的蓝图吗?
感谢您的帮助!