5

我需要将输入字符串(来自数据库)编译为函数并运行它。这是我目前使用的方法:

假设我已经定义了这个函数:

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()which 来调用它: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,但我很困惑它如何帮助我做我已经用上面的代码做的事情。

  1. 我怎样才能使用 AST 完成同样的事情?或者 AST 在这个过程中可以在哪里帮助我?
  2. 使用 AST 的实现是否更好,为什么?
4

1 回答 1

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)))

这里有一个很好的教程和文档

于 2012-11-12T19:24:28.363 回答