How to compile text as a function using AST?

abstract-syntax-tree, exec, python

Solution

AST is a much safer choice when evaluating untrusted code, that could contain malicious instructions, `eval` or `exec` can execute any expression, while AST on the other hand, allows you to parse and validate the expression yourself, or execute a limited expression using `ast.literal_eval`, sort of like a sandbox, which allows only strings, lists, numbers and a few other things. This is just a simple example:

import ast
a = ast.literal_eval("[1,2,3,4]") //evaluate an expression safely.

Another example that parses a string into an AST:

import ast
source = '2 + 2'
node = ast.parse(source, mode='eval')
ast.dump(node)

This prints:

Expression(body=BinOp(left=Num(n=2), op=Add(), right=Num(n=2)))

There's a very good tutorial here and also the documentation

Problem

I need to compile an input string (from a database) as a function and run it. This is the method I currently use: Say I already have this function defined: ``` def foo(): print "Yo foo! I am a function!" ``` And the string I read in from the database says I should call this function: ``` string_from_db = "foo()" ``` I then form a function (whose name I can control) which returns the function I read in from the database: ``` my_func_string = "def doTheFunc():\n\t return " + string_from_db ``` Now I compile the string, and set it to a function name I use later for processing: ``` exec my_func_string processor = doTheFunc ``` I can call it later by running `processor()` which exclaims: `Yo foo! I am a function!` My Question: Above this piece of code there is a comment (left by a long lost developer): ``` ############################################################### # 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 # ############################################################### ``` I'd like to know more about this "potential replacement." I have taken a look at AST, but I am very confused on how it can help me do what I am already doing with the code above. - How can I accomplish the same thing using AST? Or where can AST help me in this process? - Is the implementation using AST better, and why?

Original source