din*_*elk 6 python exec abstract-syntax-tree
我需要将输入字符串(来自数据库)编译为函数并运行它.这是我目前使用的方法:
说我已经定义了这个功能:
def foo():
print "Yo foo! I am a function!"
Run Code Online (Sandbox Code Playgroud)
我从数据库中读到的字符串说我应该调用这个函数:
string_from_db = "foo()"
Run Code Online (Sandbox Code Playgroud)
然后我形成一个函数(我可以控制其名称),它返回我从数据库中读入的函数:
my_func_string = "def doTheFunc():\n\t return " + string_from_db
Run Code Online (Sandbox Code Playgroud)
现在我编译字符串,并将其设置为我稍后用于处理的函数名称:
exec my_func_string
processor = doTheFunc
Run Code Online (Sandbox Code Playgroud)
我可以稍后通过运行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 #
###############################################################
Run Code Online (Sandbox Code Playgroud)
我想更多地了解这种"潜在替代品".我已经看了AST,但是我很困惑它如何帮助我做我已经在做的上面的代码.
在评估不受信任的代码时,AST是一个更安全的选择,它可能包含恶意指令,eval或者exec可以执行任何表达式,而另一方面,AST允许您自己解析和验证表达式,或者使用有限的表达式ast.literal_eval,类似于沙盒,只允许字符串,列表,数字和其他一些东西.这只是一个简单的例子:
import ast
a = ast.literal_eval("[1,2,3,4]") //evaluate an expression safely.
Run Code Online (Sandbox Code Playgroud)
另一个将字符串解析为AST的示例:
import ast
source = '2 + 2'
node = ast.parse(source, mode='eval')
ast.dump(node)
Run Code Online (Sandbox Code Playgroud)
这打印:
Expression(body=BinOp(left=Num(n=2), op=Add(), right=Num(n=2)))
Run Code Online (Sandbox Code Playgroud)