jakevdp jakevdp - 2 months ago 21
Python Question

Why does Python 3 exec() fail when specifying locals?

The following executes without an error in Python 3:

code = """
import math

def func(x):
return math.sin(x)

func(10)
"""
_globals = {}
exec(code, _globals)


But if I try to capture the local variable dict as well, it fails with a
NameError
:

>>> _globals, _locals = {}, {}
>>> exec(code, _globals, _locals)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-9-aeda81bf0af1> in <module>()
----> 1 exec(code, {}, {})

<string> in <module>()

<string> in func(x)

NameError: name 'math' is not defined


Why is this happening, and how can I execute this code while capturing both global and local variables?

Answer

From the exec() documentation:

Remember that at module level, globals and locals are the same dictionary. If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.

You passed in two separate dictionaries, but tried to execute code that requires module-scope globals to be available. import math in a class would produce a local scope attribute, and the function you create won't be able to access that as class scope names are not considered for function closures.

Just pass in one dictionary.