我想从用户输入调用一个函数,但在括号中包含参数.例如,如果我有一个带有一个参数的函数:
def var(value):
print(value)
Run Code Online (Sandbox Code Playgroud)
我想问用户一个命令和参数,然后用参数调用该函数:
Input Command: var("Test")
Test
Run Code Online (Sandbox Code Playgroud)
从参数中拆分函数名称.使用预定义的地图按名称查找功能.解析参数literal_eval.使用参数调用函数.
available = {}
def register_func(f):
available[f.__name__] = f
@register_func
def var(value):
print(value)
from ast import literal_eval
def do_user_func(user_input):
name, args = user_input.split('(', 1)
return available[name](*literal_eval('(' + args[:-1] + ',)'))
do_user_func("var('test')") # prints "test"
Run Code Online (Sandbox Code Playgroud)
这仍然非常脆弱,任何无效的输入都将失败(例如忘记括号或无效的函数名称).这取决于你使这个更强大.
literal_eval在不受信任的输入上仍然有些不安全,因为可以构造评估为大量内存的小字符串.'[' * 10 + ']' * 10,为了一个安全但具有示范性的例子.
最后,不要eval在不受信任的用户输入上使用.没有切实可行的方法来保护它免受恶意输入. 虽然它会评估您期望的良好输入,但它也会评估代码,例如,将删除所有文件.
任何eval安全的尝试最终都会比这里的任何解决方案都更复杂,没有任何实际好处.它在某种程度上仍然不会安全,你没有预料到.不要这样做.