Get the value of the last expression in the `exec` call

Say I have python code in line

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

and I exec this line of code:

 result = exec(code) 

Then result will always be None . Is there any way to get an estimate of the last expression? In this case, it will be 5 , since a was the last expression.

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

 a = 100 sqrt(a) 

Then how can I execute the code in such a way as to give me a result of 10 - i.e. sqrt(a) ?

EDIT EDIT: Another example: the code I want exec ,

 function_a() function_b() function_c() 

Is there any way to define any magic_exec function magic_exec that

 magic_exec(code) 

will provide me the value of function_c() ?

+1
source share
4 answers
 exec('a = 4') print a % prints 4 >>> code = """ ... a = 42 ... b = 53""" >>> exec(code) >>> a 42 >>> b 53 

Or, if you say that you do not know what the latter is, for example, b, then you can do this:

 code = """ a = 4 b = 12 abc_d=13 """ t = re.findall(r'''.*?([A-Za-z0-9_]+)\s*?=.*?$''', code) assert(len(t)==1) print t[0] % prints 13 
0
source

This does not give you the last evaluated value, but gets the entire list of local variables.

 >>> loc = {} >>> exec(code, {}, loc) >>> loc {'a': 42} 
0
source

Honestly, I can’t say that I am very pleased with this. It feels very hacked, and I have not tested it all so much. On the other hand, I am very pleased with this. It was pretty fun. In any case, I hope this helps you, or at least comes close to what you want. locals() gives a dict, so the order of the output list does not match the input order for elements that did not perform the first eval . If you do not want ';' as delimiters, you can change it to '\n' .

 import math def magic_exec(_command): _command = _command.split(';') _result = None _before = list(locals()) # Get list of current local variables for _code in _command: _code = _code.strip() # .strip() prevent IndentationError try: if eval(_code) != None: # For functions with no return _result = eval(_code) except (NameError, SyntaxError): try: _before = list(locals()) exec(_code) except NameError as e: # For undefined variables in _command print("An Error Occurred with line ' {0} ' as was skipped: {1}".format(_code, e)) del _code # delete temp var _code # Get new list of locals that didn't exist at the start _after = [val for val in list(locals()) if val not in _before] if _after: return eval(_after[0]) else: return _result #Dummy class and functions class Class1(object): def __init__(self, x): self._x = x def get_val(self): return self._x def __repr__(self): return type(self).__name__ def func1(x): return x + x def func2(x): print(x*x) if __name__ == '__main__': code = \ """ a = 42; a; v; y = 2; b = func1(5); s = 'Hello'; func2(10); c = 25; l = []; l.append('Value'); t = math.sqrt(c); pass; 20*10; print('TEST'); math.sqrt(c); d = Class1('World'); d.get_val(); def func3(x): return x ** 2; s = func3(15) """ values = magic_exec(code) print(values) 
0
source

The request is certainly valid, since I also need such a function during the creation of the Python-based environment. I solved the problem with the following code that uses 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 clear, basically it

  • separate script from multiple statements
  • if the latter is an expression, execute the first part as instructions and the last part as an expression.
  • Otherwise, follow all script as instructions.
0
source

All Articles