Search code examples
pythonscopepython-exec

Python exec not picking up scope when called via a function


I have a function test() that should check if a string is a valid Python file. (The string is typically extracted from a readme or so.) Running exec() on the string works well, unless in this situation:

string = """
import math

def f(x):
    return math.sqrt(x)

f(2.0)
"""

# no problem:
# exec(string)


def test():
    exec(string)

test()  # NameError: name 'math' is not defined
Traceback (most recent call last):
  File "d.py", line 17, in <module>
    test()
  File "d.py", line 15, in test
    exec(string)
  File "<string>", line 7, in <module>
  File "<string>", line 5, in f
NameError: name 'math' is not defined

Why does exec() not pick up on the import math if called through a function, but works when running it in the main scope? How to work around it within test()?


Solution

  • It's a bit hard to explain properly but it will work if you do this:

    def test():
        exec(string, {"__MODULE__": "__main__"})
    

    Basically, the import math does not exist in the f function unless it's declared in the main scope.