But the code
outputs 2. Should not
always have the same effect as
in code? I am not sure if this is bug or intended this way.
This is working as intended as you didn’t pass anything into your
exec() that would cause it to work outside of itself. In other words
exec() knows nothing about namespaces, so you have to pass that sort of stuff in (run
help(exec) for more details).
Brett, your answer is incomplete and misleading in three ways.
It’s not true that exec without a namespace argument doesn’t modify the
local environment. It behaves as Olle7 expects in the global and class
x = 2
exec("x = 1")
print(x) # -> prints 1, not 2
x = 2
exec("x = 999")
print(x) # -> prints 999
With no additional arguments, the exec function defaults to
Secondly, it also works as Olle7 expects inside functions in Python 2.
And thirdly, even if we explicitly pass
locals() to exec, it still
won’t work inside a function in Python3, at least not in CPython. (Other
Python implementations may differ.)
Olle7, the behaviour you see is intentional, it is an optimisation to
help functions run faster. It is not a language feature, but a
limitation of CPython that the local namespace inside a function is
special. Both eval and exec can read variables but exec may not be able
to write variables inside a function. There are notes about this in the
I seem to remember the docs explicitly mentioning that this was an
implementation detail, not a language feature, but I can’t find that
now and don’t have time to go looking.
In any case, from time to time people suggest changing the behaviour to
operate as expected, but such proposals haven’t gone anywhere as yet.
No worries Brett its an obscure corner of behaviour of a function which
is rarely used.
I now understand execs behavior when it is called in function better.
print("x is not reachable.")
print("x in dict returned by function locals:",locals()["x"])
print("x was not reachable on line 4 althought it is in locals, beacuse it was added to locals in exec in function, which causes undefined behaivor.")
print("x must be reachable in another exec.")
eval("print('x and y are also reachable in eval. x:',x,'; y:',y)")
exec("global g1\ng1='G1 AFTER'")
if "g1" in globals() and "g1" not in locals():
print("gloabal variable g1:",g1)
if "g2" in locals():
print("local variable g2:",g2)
print("g2 was not treated as global variable, because it is decleared global outside of exec")
print("local variables: ",locals())
print("global variables: ", globals())
print("there is also a global varable g2:",g2)
program goes to all if’s.