假设我有一个如下的函数,我想根据变量名有多个函数。
@app.route('/foo', methods=['GET', 'POST'])
def foo():
print("food")
return "OK"
我想根据变量名声明多个函数,我是这样实现的。
from flask import Flask
app = Flask(__name__)
methods = ['GET', 'POST']
names = ['foo', 'fubu', 'fomo', 'bar']
for name in names:
exec(f"""
@app.route('/{name}', methods=methods)
def {name}():
print('NAMED {name}')
return '{name} - Example'
""")
我读到这样的使用方法 exec() 是 极不情愿 要用,如果用了就意味着我做错了。
请问有什么最好的方法来实现,因为这种方法是不好的。
我想实现的是让我的应用接受存储在内存中的额外的JSON配置文件,并包含所有这些指令,如果主管理员在编辑时输入正确的第二长密码,则加载它们。
从问题的评论来看。
@LoïcFaure-Lacroix 我想让管理员能够添加新的路由,而不需要硬编码,我的意思是管理员可以选择加载哪些模块,路由名称,数据库模型,也可以添加代码,在该路由中执行... ... 必须提供第二个密码才能修改配置文件
我不会让你这么做。任何有正确凭证的人都能直接在服务器上执行代码,并给运行应用程序的用户提供几乎所有的凭证来执行任何事情。
你可以使用 编制 与 exec
来快速生成代码。思想,我相信你想实现这个目标的原因是错误的。
如果你想在运行时扩展你的应用程序,你最好在你的应用程序中加入一个插件api。
就像这样。
class MyPlugin(Plugin):
def info(self):
# return information about the module/plugin
def register(self, application):
# register the plugin into the application
def unregister(self):
# do cleanup
所以你的每一个插件都可以被定义为可以安装的python包。每一个python包都会暴露出一个入口点,甚至是命名空间模块。
https:/packaging.python.orgguidescreating-and-discovering-plugins。
当你得到你的 entrypointmodule,你调用插件类或简单的方法来注册它。
你的主程序要做的就是在运行时发现已安装的插件并加载卸载它们。
你直接在服务器上执行代码的问题是它不可维护。你没有任何设施来卸载你所做的改变,事情迟早会崩溃。让python代码编译是一个巨大的安全风险,如果你能通过手动安装一套可以在运行时被发现的包来摆脱,这样更安全,更容易管理。
凡是涉及到添加更多的路由,可以用你所使用的库的API来完成,凡是涉及到添加配置文件数据库等。都可以直接通过存储配置来完成。在99%的情况下,几乎没有理由直接从python代码内编译python代码。
名字可能并不重要。比如,你可以这样做。
def function_maker(name):
def _():
print(f'Named {name}')
return '{name} - Example'
_.__name__ = name
return _
然后
for name in ['foo', 'fubu', 'fomo', 'bar']:
@app.route(f'/{name}', methods=methods)(function_maker(name))
的定义可能会有细微的差别。def foo():...
和 def _():...
但这些都不可能是重要的。