如何使用AST将文本编译为函数?

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,但是我很困惑它如何帮助我做我已经在做的上面的代码.

  1. 如何使用AST完成同样的事情?或者AST在这个过程中可以帮助我?
  2. 使用AST的实现更好,为什么?

iab*_*der 5

在评估不受信任的代码时,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)

有一个很好的教程在这里,也是文档