-1

How would I do the following:

>>> new=exec('i=100;2 if i > 4 else 3')
>>> repr(new)
'None'

I want to get 2:

>>> i=100
>>> 2 if i>4 else 3
2

I can do this with eval, as long as there isn't an assignment:

>>> new=eval('2 if i>4 else 3')
>>> new
2

In other words, how to execute a string of code (with an assignment, not just eval) and get the last part?


Here is a related question from ~5 years ago: not sure if the answers still apply though, or anything has changed since then: How do I get the return value when using Python exec on the code object of a function?.

David542
  • 104,438
  • 178
  • 489
  • 842

2 Answers2

2

You can pass a dict to be used for the global namespace. Assign the result to a global variable and you can read it later.

>>> data = {}
>>> exec('i=100;result = 2 if i > 4 else 3', data)
>>> data['result']
2

By default exec uses the module's namespace. If you don't mind the exec'd script's variables messing with your own variables, you could leave the global dict out.

>>> exec('i=100;result = 2 if i > 4 else 3')
>>> result
2

You run the risk of accidentally overwriting data unexpectedly if you don't notice the use of a variable in the string. But its certainly an option.

You can also use 2 dictionaries, one for globals and one for locals and the variables you create will end up in the latter.

>>> data1={}
>>> data2={}
>>> exec('i=100;result = 2 if i > 4 else 3', data1, data2)
>>> data2
{'i': 100, 'result': 2}

Notice that all of the variables you create in the executed script end up in the namespace dictionaries.

tdelaney
  • 73,364
  • 6
  • 83
  • 116
  • that's great, I can just add in `result=` to the last statement and it'll give me exactly what I need. – David542 Dec 27 '20 at 05:49
1

Just split on semicolon into two parts:

exec('i=100')
new=eval('2 if i>4 else 3')
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • ah, I see that's pretty neat. So basically go through the (string) statement and if there's an `=` operator in it split until the next `;` and put that in `exec`, otherwise put it in `eval` ? – David542 Dec 27 '20 at 05:46
  • 1
    [Here](https://stackoverflow.com/questions/39379331/python-exec-a-code-block-and-eval-the-last-line) you'll find a more general solution along these lines. (Can't immediately find anyone else using semicolons like that in Python, though.) – Noah Dec 27 '20 at 05:49