我需要将输入字符串(来自数据库)编译为函数并运行它。这是我目前使用的方法:
说我已经定义了这个功能:
def foo():
print "Yo foo! I am a function!"
我从数据库中读到的字符串说我应该调用这个函数:
string_from_db = "foo()"
然后我形成一个函数(我可以控制其名称),它返回我从数据库中读入的函数:
my_func_string = "def doTheFunc():\n\t return " + string_from_db
现在我编译字符串,并将其设置为稍后用于处理的函数名称:
exec my_func_string
processor = doTheFunc
我可以稍后通过运行processor()
来调用它:Yo foo! I am a function!
我的问题:在这段代码之上有一条评论(由一位长期失去的开发者留下):
###############################################################
# The following method for getting a function out of the text #
# in the database could potentially be replaced by using #
# Python's ast module to obtain an abstract syntax tree and #
# put it inside of a function node #
###############################################################
我想更多地了解这种“潜在替代品”。我已经看了AST,但是我对它如何帮助我做上面的代码所做的事情感到非常困惑。
答案 0 :(得分:5)
在评估不受信任的代码时,AST是一个更安全的选择,可能包含恶意指令,eval
或exec
可以执行任何表达式,而另一方面,AST允许您解析和验证表达自己,或使用ast.literal_eval
执行有限的表达式,有点像沙盒,它只允许字符串,列表,数字和其他一些东西。这只是一个简单的例子:
import ast
a = ast.literal_eval("[1,2,3,4]") //evaluate an expression safely.
将字符串解析为AST的另一个示例:
import ast
source = '2 + 2'
node = ast.parse(source, mode='eval')
ast.dump(node)
打印:
Expression(body=BinOp(left=Num(n=2), op=Add(), right=Num(n=2)))
有一个非常好的教程here以及documentation