Consider this working code:
x=123
def printx():
print(x)
If I execute printx()
the output would be 123
as x
value exists in locals()
and printx
sees that.
I can also get x
value like this:
locals()["x"]
But I need to run my function in exec with global and local parameters supplied, so I wrote this code, which should be identical in purpose to the first snippet:
glo = dict()
loc = dict()
exec('x=123', glo, loc)
exec('def printx():\n print(x)', glo, loc)
However, when I call printx()
I get this error:
exec('printx()', glo, loc)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
File "<string>", line 2, in printx
NameError: name 'x' is not defined
Yet both loc["x"]
and eval('x', glo, loc)
return 123
as expected.
How can I make locals and globals available for my printx
function?
I want printx
to behave the same in exec
with context?
If a local dict is provided, "eval" runs in that local namespace. All changes go in that local namespace. You can see that by printing loc
after your commands. Both x
and printx
are in that namespace. Calling a function establishes a new local namespace. Python doesn't nest namespaces, so all it has available is its new (empty) local namespace and the global namespace, and x
is in neither of those.
You should probably run your first two eval
s with the global namespace only. That way, your code will work, even if it is a horrible way to do Python programming.