Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

scope of globals, locals, use with exec()

I’m having a hard time understanding the scope of globals(), locals() in Python. Consider the following code:

def f1(glob, loc):
    exec("b = 5", glob, loc)


f1(globals(), locals())
print(b + 1)

This passes globals and locals to f1 where the variable b = 5 is defined, and sure enough it’s present after the function call in the main scope. The code correctly prints

6

To my surprise, when doing the same in the scope of a function, f2 here, it fails:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

def f1(glob, loc):
    exec("b = 5", glob, loc)


def f2():
    f1(globals(), locals())
    print(b + 1)


f2()
Traceback (most recent call last):
  File "/tmp/q.py", line 10, in <module>
    f2()
  File "/tmp/q.py", line 7, in f2
    print(b + 1)
NameError: name 'b' is not defined

Why is that? Is it possible to generalize f1 to allow it to be called from f2 as well?

>Solution :

In your first example, locals is the globals dict, because you’re on a module level.

You can check that with print(id(globals()), id(locals()))

In your second example, locals is a different dict in the scope of the function.

So to make example 2 work, either use:

def f1(glob, loc):
    exec("b = 5", glob, loc)
def f2():
    f1(globals(), globals())
    print(b + 1)
f2()

or

def f1(glob, loc):
    exec("b = 5", glob, glob)
def f2(loc):
    f1(globals(), loc)
    print(b + 1)
f2(locals())

So this isn’t really a matter of exec() but of in which scope you’re calling locals().

And ofc it’s also a matter of what the code in exec does, because an assignment changes the scope of the name to the current (local) scope, unless global/nonlocal is involved. That’s why b=5 is executed in the local scope – except that in your first example, the "local" scope is the global scope.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading