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 Overflow
Top answer
1 of 4
20

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.

2 of 4
9

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)
🌐
AskPython
askpython.com › home › understanding the python exec() method
Understanding the Python exec() Method - AskPython
August 6, 2022 - For string – the string is parsed as a suite of Python statements which is then executed (unless a syntax error occurs). For an open file – the file is parsed until EOF and executed. For a code object – it is simply executed. And the two optional arguments globals and locals must be dictionaries used for the global and local variables.
Discussions

How to set a variable as global with python’s exec() function?
I strongly recommend you avoid using global if you can. It can cause you lots of problems with larger programmes, especially if you break them up into modules. While not use class instance attributes, or a mutable data structure in scope of all of the functions? More on reddit.com
🌐 r/learnpython
13
3
January 30, 2020
Problem with globals in exec()'d code
This Python snippet: code = compile(""" a=1 b=2 def result(): return a+b """, " ", "exec") g={} l={} exec(code, g,l) assert l["result"]() == 3 results in a funky error: Traceback (most recent call last): File "/tmp/t.py", line 12, in assert l["result"]() == 3 ^^^^^^^^^^^^^ File " ", line 5, ... More on discuss.python.org
🌐 discuss.python.org
0
0
October 23, 2024
python - Understanding exec statement with a globals parameter - Stack Overflow
I have a python script that I'm picking up from someone else and am trying to understand what's happening when it runs. I have a file in my current directory called __version__.py that contains the More on stackoverflow.com
🌐 stackoverflow.com
Where is it documented that exec() makes changes only in the locals dict? - Documentation - Discussions on Python.org
Where is it documented that exec() makes changes only in the locals dict · I understand that exec() modifies its locals argument. But where is this in the documentation · EDIT: The answer is that the ‘x = 1’ statement makes x a local variable, so obviously the update will happen in loc More on discuss.python.org
🌐 discuss.python.org
0
September 25, 2022
🌐
DEV Community
dev.to › sachingeek › how-to-use-exec-in-python-everything-you-need-to-know-380f
How to Use exec() in Python - Everything You Need to Know - DEV Community
July 30, 2023 - The globals parameter specifies the variables str1 and str2, while the locals parameter specifies the variable x. Using the globals and locals params, we can control whether to restrict or use any variable or method in our code input.
🌐
Real Python
realpython.com › python-exec
Python's exec(): Execute Dynamically Generated Code – Real Python
November 10, 2022 - If code holds a compiled code object, ... more efficient. The globals and locals arguments allow you to provide dictionaries representing the global and local namespaces in which exec() will run the target code....
🌐
EDUCBA
educba.com › home › software development › software development tutorials › python tutorial › exec python
exec Python | How exec works in Python with Examples
April 11, 2023 - These global parameters restrict the execution of the code within the boundary values defined in Exec statement. These global variables are independent of any functions and are used globally anywhere in the program.
Address   Unit no. 202, Jay Antariksh Bldg, Makwana Road, Marol, Andheri (East),, 400059, Mumbai
🌐
Reintech
reintech.io › blog › python-understanding-the-exec-method
Python: Understanding the exec() Method | Reintech media
January 20, 2026 - A dictionary defining the local namespace. If omitted but globals is provided, globals serves as both. If both are omitted, the current namespace is used. At its simplest, exec() runs a string of Python code:
🌐
GitHub
gist.github.com › dean0x7d › df5ce97e4a1a05be4d56d1378726ff92
Python's exec and locals() vs globals() · GitHub
Python's exec and locals() vs globals(). GitHub Gist: instantly share code, notes, and snippets.
🌐
Python
docs.python.org › 2.0 › ref › exec.html
6.13 The exec statement
Programmer's hints: dynamic evaluation of expressions is supported by the built-in function eval(). The built-in functions globals() and locals() return the current global and local dictionary, respectively, which may be useful to pass around for use by exec.
Find elsewhere
🌐
Scaler
scaler.com › home › topics › exec() in python
exec() in Python - Scaler Topics
May 4, 2023 - The python exec() function takes ... the code or string to the exec() function for further execution. globals : It is an optional parameter....
🌐
DataFlair
data-flair.training › blogs › python-exec-function
Python exec Function - Example and Risk - DataFlair
April 14, 2026 - ... Let’s check the help for this. ... Help on built-in function exec in module builtins: exec(source, globals=None, locals=None, /) Execute the given source in the context of globals and locals.
🌐
Reddit
reddit.com › r/learnpython › how to set a variable as global with python’s exec() function?
r/learnpython on Reddit: How to set a variable as global with python’s exec() function?
January 30, 2020 -

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
🌐
Python Geeks
pythongeeks.org › python geeks › learn python › python exec() with examples
Python exec() with Examples - Python Geeks
November 1, 2021 - The following points describe the three arguments : 1. object: It is either a string or an object to be executed · 2. globals: This is a dictionary that contains the global methods and variables
🌐
Geek Python
geekpython.in › exec-function-in-python
exec() Function In Python - Detailed Guide With Code
August 15, 2023 - The globals parameter specifies the variables str1 and str2, while the locals parameter specifies the variable x. Using the globals and locals params, we can control whether to restrict or use any variable or method in our code input.
🌐
Medium
pythonflood.com › boost-your-coding-abilities-with-python-exec-function-bec400c53e9c
Boost Your Coding Abilities with Python exec() Function | by Rinu Gour | PythonFlood
October 21, 2023 - In this example, we define a string of Python code `code` and pass it to the `exec()` function along with an empty `globals` dictionary and a `locals` dictionary containing the variables `x` and `y`. When the code is executed, it uses the values of `x`and `y` from the `locals` dictionary rather than the global namespace.
🌐
Python.org
discuss.python.org › python help
Problem with globals in exec()'d code - Python Help - Discussions on Python.org
October 23, 2024 - This Python snippet: code = compile(""" a=1 b=2 def result(): return a+b """, " ", "exec") g={} l={} exec(code, g,l) assert l["result"]() == 3 results in a funky error: Traceback (most recent call last): File "/tmp/t.py", line 12, in assert ...
🌐
Programiz
programiz.com › python-programming › methods › built-in › exec
Python exec() (With Examples)
Most of the time, we don't need all the methods and variables with exec(). We can block these unnecessary methods and variables by passing the optional globals and locals parameter to the exec() method.
🌐
Finxter
blog.finxter.com › home › learn python blog › python exec() — a hacker’s guide to a dangerous function
Python exec() - A Hacker's Guide to A Dangerous Function - Be on the Right Side of Change
June 7, 2022 - The reason for this NameError is that the global variable x is not part of the new global namespace because you passed the empty dictionary as a globals argument into the exec() function. In a similar manner, you can pass a dictionary as a second argument to the exec() function to customize the use of your local namespace. Otherwise, Python will just use the global default namespace of your program as a local namespace.
🌐
Stack Overflow
stackoverflow.com › questions › 59185550 › understanding-exec-statement-with-a-globals-parameter
python - Understanding exec statement with a globals parameter - Stack Overflow
The __builtins__ key that gets added is precisely how the execed code gets access to the built-in functions, types, exceptions, etc. If you didn't want that to happen, I believe you could pass a globals dictionary like { '__builtins__': {} }. ... gdict from your program changes because python dictionaries are mutable.
🌐
Python.org
discuss.python.org › documentation
Where is it documented that exec() makes changes only in the locals dict? - Documentation - Discussions on Python.org
September 25, 2022 - glob = {} loc = {} exec(‘x = 1’, glob, loc) ‘x’ not in glob assert loc[‘x’] == 1 I understand that exec() modifies its locals argument. But where is this in the documentation? EDIT: The answer is that the ‘x = 1’ statement makes x a local variable, so obviously the update will happen in loc.
🌐
Python
bugs.python.org › issue38331
Issue 38331: Exec not recognizing global variables inside function - Python tracker
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 · This issue has been migrated to GitHub: https://github.com/python/cpython/issues/82512