Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get value of last expression in `exec` call

Let's say I have some python code in a string

code = """
a = 42
a
"""

and I exec that string of code:

result = exec(code)

Then result will always be None. Is there any way at all to get the value of the last expression evaluated? In this case, that would be 5, since a was the last expression.

EDIT: Here's another example of the functionality I'm asking about. Let's say we have the python code (stored in the variable code)

a = 100
sqrt(a)

Then how can I execute the code in such a way as to give me the result 10 - that is, sqrt(a)?

EDIT EDIT: A further example: the code I wish to exec is

function_a()
function_b()
function_c()

Is there any way I can define some kind of magic_exec function so that

magic_exec(code)

will provide me with the value of function_c()?

like image 838
feralin Avatar asked Nov 25 '15 05:11

feralin


People also ask

How do I return a value in exec?

What does exec return in Python? Python exec() does not return a value; instead, it returns None. A string is parsed as Python statements, which are then executed and checked for any syntax errors. If there are no syntax errors, the parsed string is executed.

What is exec () in Python?

The exec() function executes the specified Python code. The exec() function accepts large blocks of code, unlike the eval() function which only accepts a single expression.

What is the difference between eval and exec in Python?

Eval() only evaluates the single expression, not the complex logic code, whereas Exec can be used to execute any number of expression. exec() accept the source code which contains statements like, for, while, print, import, class, if we pass these statement to eval() it will throw error.

How do you run a dynamic code in Python?

To execute dynamically generated Python code, use Python's exec function; to evaluate a dynamically generated Python expression, use Python's eval function. Beware: using these functions (or any of the below) with input from the user potentially allows the user to execute arbitrary code.


1 Answers

The request is certainly valid because I need such a function as well during the creation of a Python-based environment. I solved the problem with the following code that utilizes the Python ast mechanism:

def my_exec(script, globals=None, locals=None):
    '''Execute a script and return the value of the last expression'''
    stmts = list(ast.iter_child_nodes(ast.parse(script)))
    if not stmts:
        return None
    if isinstance(stmts[-1], ast.Expr):
        # the last one is an expression and we will try to return the results
        # so we first execute the previous statements
        if len(stmts) > 1:
            exec(compile(ast.Module(body=stmts[:-1]), filename="<ast>", mode="exec"), globals, locals)
        # then we eval the last one
        return eval(compile(ast.Expression(body=stmts[-1].value), filename="<ast>", mode="eval"), globals, locals)
    else:
        # otherwise we just execute the entire code
        return exec(script, globals, locals)

The code should be pretty self-explanatory, basically it

  1. separate the script into multiple statements
  2. if the last one is an expression, execute the first part as statements, and the last part as expression.
  3. Otherwise execute the entire script as statements.
like image 98
user2283347 Avatar answered Oct 07 '22 01:10

user2283347