Well, I believe it's either an implementation bug or an undocumented design decision. The crux of the issue is that a name-binding operation in the module-scope should bind to a global variable. The way it is achieved is that when in the module level, globals() IS locals() (try that one out in the interpreter), so when you do any name-binding, it assigns it, as usual, to the locals() dictionary, which is also the globals, hence a global variable is created.
When you look up a variable, you first check your current locals, and if the name is not found, you recursively check locals of containing scopes for the variable name until you find the variable or reach the module-scope. If you reach that, you check the globals, which are supposed to be the module scope's locals.
>>> exec(compile("import sys\nprint sys._getframe().f_code.co_name", "blah", "exec"), {}, {})
<module>
>>> exec("a = 1\nclass A(object):\n\tprint a\n", {}, {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 2, in <module>
File "<string>", line 3, in A
NameError: name 'a' is not defined
>>> d = {}
>>> exec("a = 1\nclass A(object):\n\tprint a\n", d,d)
1
This behavior is why inheritance worked (The name-lookup used code object's scope locals(), which indeed had A in it).
In the end, it's an ugly hack in the CPython implementation, special-casing globals lookup. It also causes some nonsensical artifical situations - e.g.:
>>> def f():
... global a
... a = 1
...
>>> f()
>>> 'a' in locals()
True
Please note that this is all my inference based on messing with the interpreter while reading section 4.1 (Naming and binding) of the python language reference. While this isn't definitive (I haven't opened CPython's sources), I'm fairly sure I'm correct about the behavior.
Answer from Roee Shenberg on Stack OverflowWell, I believe it's either an implementation bug or an undocumented design decision. The crux of the issue is that a name-binding operation in the module-scope should bind to a global variable. The way it is achieved is that when in the module level, globals() IS locals() (try that one out in the interpreter), so when you do any name-binding, it assigns it, as usual, to the locals() dictionary, which is also the globals, hence a global variable is created.
When you look up a variable, you first check your current locals, and if the name is not found, you recursively check locals of containing scopes for the variable name until you find the variable or reach the module-scope. If you reach that, you check the globals, which are supposed to be the module scope's locals.
>>> exec(compile("import sys\nprint sys._getframe().f_code.co_name", "blah", "exec"), {}, {})
<module>
>>> exec("a = 1\nclass A(object):\n\tprint a\n", {}, {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 2, in <module>
File "<string>", line 3, in A
NameError: name 'a' is not defined
>>> d = {}
>>> exec("a = 1\nclass A(object):\n\tprint a\n", d,d)
1
This behavior is why inheritance worked (The name-lookup used code object's scope locals(), which indeed had A in it).
In the end, it's an ugly hack in the CPython implementation, special-casing globals lookup. It also causes some nonsensical artifical situations - e.g.:
>>> def f():
... global a
... a = 1
...
>>> f()
>>> 'a' in locals()
True
Please note that this is all my inference based on messing with the interpreter while reading section 4.1 (Naming and binding) of the python language reference. While this isn't definitive (I haven't opened CPython's sources), I'm fairly sure I'm correct about the behavior.
After print locals() and globals(),you will find the reason why exec throws "not defined" exception, and you can try this
d = dict(locals(), **globals())
exec (code, d, d)
How to set a variable as global with python’s exec() function?
Problem with globals in exec()'d code
python - Understanding exec statement with a globals parameter - Stack Overflow
Where is it documented that exec() makes changes only in the locals dict? - Documentation - Discussions on Python.org
For purposes in a large program, I need to scan through a data file. Every time certain objects are found in the first column, data is grabbed from that respective column element’s row to compute a large matrix. That same matrix is further manipulated by other functions associated with other objects. I want to create separate variables that represent the state of the array after passing through a function related to each object, and store it as a global variable to be grabbed for later use. I have the general code structure down to create the variable once an object in the data file is found, I just don’t know how to set them all as global individually using exec. Any help is appreciated!
The logic looks like this:
this function has other arguments to manipulate array_out, but I’m only putting the variable i here since it’s relevant to the variables created with exec. It is the i from “for i in...” in function2().
Object1_function(i):
#some math is done to manipulate array_out. exec(‘data_’+str(i)+’=array_out’) return [array_out]
function2():
for i in range(data.shape[0]):
column_object = data[i][0]
if ‘object1’ in column_object;
Object1_function(i) #uses exec to create array_out variable associated with object1