This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author steven.daprano
Recipients qpeter, steven.daprano
Date 2021-12-22.17:05:56
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1640192756.24.0.434073489729.issue46153@roundup.psfhosted.org>
In-reply-to
Content
Here is the key phrase in the docs:

"If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition."

https://docs.python.org/3/library/functions.html#exec

And sure enough:

>>> class C:
...     a = 1
...     def f():
...             return a  # This looks for global a, not C.a
...     print(f())
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in C
  File "<stdin>", line 4, in f
NameError: name 'a' is not defined

which is intentional behaviour. Functions defined inside a class do not have direct access to the variables inside the class. I thought there was a FAQ about this but I can't find it now.

So there is no bug here. By passing two distinct dicts as the globals and locals to exec, the interpreter treats the code as if it were being executed inside the body of a class statement. Both the a and the f get created in the locals dict, not the globals dict:

>>> g = {'__builtins__': None}
>>> l = {}
>>> exec("""a = 1
... def f():
...     return a
... """, g, l)
>>> g
{'__builtins__': None}
>>> l
{'a': 1, 'f': <function f at 0x7fa07b83e0e0>}

But when you call f(), it is looking for a in the globals dict.
History
Date User Action Args
2021-12-22 17:05:56steven.dapranosetrecipients: + steven.daprano, qpeter
2021-12-22 17:05:56steven.dapranosetmessageid: <1640192756.24.0.434073489729.issue46153@roundup.psfhosted.org>
2021-12-22 17:05:56steven.dapranolinkissue46153 messages
2021-12-22 17:05:56steven.dapranocreate