-3

In Python this works:

exec('x = 1; y = 2')

so you have both x and y created successfully:

>>> x,y
(1,2)

But this does not work:

def DoIt():
    exec('x = 1; y = 2')
    return x,y

>>> DoIt()
...
NameError: name 'x' is not defined

Why? Any solution?

================================================

Edit: Very Strange and Unexpected: The above works on Python 2.7

Check out on https://repl.it/languages/python

Anyway, I am using Python 3.5 64Bit and it does not work at all! The Python 2.7 is not a solution for me.

This post requires in depth knowledge of an experienced Pythonist.

Dear New Comers, first, very welcome to Stackoverflow! and WoW you started your journey with downvoting without even paying attention to what the question is all about! You can do better, be patient. Leave comments, it is OK and recommended.

And BTW, what matters to me after all is an answer to my question.

[Note]

This is not a duplicate of another question. I had to do no business with Python 2.7 to see a difference. Such bizarre behavior was discovered here following comments and previous (now deleted) answers.

So when something like this happens, you do not go to check you code if running differently in previous versions of Python. You just do not. So recommendation on this regards is irrelevant.

Community
  • 1
  • 1
Developer
  • 8,258
  • 8
  • 49
  • 58
  • I tried your code in Python 2.7.12 and it works, can you try running it again? – Fernando Irarrázaval G Apr 17 '17 at 05:31
  • @FernandoIrarrázavalG It does not work. Check the code on https://repl.it/languages/python3 you see yourself. – Developer Apr 17 '17 at 05:38
  • Very bizarre indeed! For me you example also doesn't work. However when I set a delay between `exec` and `return` it does work (e.g. when I include a line `print("DoIt")` in between `exec` and `return`) the function runs without problems. – Tom de Geus Apr 17 '17 at 05:58
  • 1
    "This post requires in depth knowledge of an experienced Pythonist." – Actually, the highest-voted answer at this point was written by someone who knows next to nothing about Python (i.e. me). This is clearly mentioned in the documentation, there is a [so] question and [answer](http://stackoverflow.com/a/15087355/2988) about it, and it all it took was typing "exec python 3" into Google. – Jörg W Mittag Apr 17 '17 at 06:05
  • 1
    Possible duplicate of [Behavior of exec function in Python 2 and Python 3](http://stackoverflow.com/questions/15086040/behavior-of-exec-function-in-python-2-and-python-3) – Jörg W Mittag Apr 17 '17 at 06:08
  • @JörgWMittag Thanks. You comment and solution teaches me a lot. – Developer Apr 17 '17 at 06:10
  • @JörgWMittag I was never expecting such bizarre behavior as it was and is a core functionality in Python. So there was no point to search for if it is the case in older Pythons. I don't use Python 2.x since years of 3.x. – Developer Apr 17 '17 at 06:15

1 Answers1

3

In Python 2, exec was a built-in statement, and it leaked its variables into the surrounding scope. This scope leak was fixed in Python 3, where exec() is now a bog-standard library function like any other. You cannot create or modify local variables of the surrounding function scope within exec().

It does work, however, in module scope, as you discovered. The documentation is clear in that it only applies to function local scope.

What you can do, is pass your own local variable dictionary:

def do_it():
    vars = {}
    exec('x = 1; y = 2', vars)
    return (vars['x'], vars['y'])
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • This is what I wanted to learn. Things like this I never know unless I ask. I learn and that matters. Thank you, indeed. – Developer Apr 17 '17 at 06:10