4

I'm trying to create a custom python interpreter type application. I'm using exec statement (in Python 2.7.6) to execute given code but globals aren't working quite as expected. Could someone explain why this does not work:

def print_x():
    print(x)


g = {'x': 10, 'print_x': print_x}
l = {}

exec('print_x()', g, l)

The result (whether the print_x function is in g or l), is an error:

NameError: global name 'x' is not defined

So, do the globals passed to exec not carry over to called functions?

4
  • So exec does not know how to parse your dictionary g Commented Jun 18, 2016 at 4:40
  • But I could use exec('print(x)', g, l) just fine. It just doesn't work with the print_x function. Commented Jun 18, 2016 at 4:41
  • stackoverflow.com/questions/2904274/… - seems similar to your case Commented Jun 18, 2016 at 4:43
  • Thank you for that link. It is similar but not quite the same as my program. I have now tried printing out globals() and locals() in the print_x() function and sure enough, 'x' is not there. I'm just not quite sure why that is. Commented Jun 18, 2016 at 4:50

1 Answer 1

3

The x inside the function is picked up from the globals of the namespace where the function is defined. However, you're calling it in a different namespace. This isn't too different from having multiple modules:

# foo.py
def print_x():
    print(x)

and then trying to use it in a different module:

# bar.py
from foo import print_x

x = 10
print_x()  # NameError

Ultimately, g is the globals in the execution context of exec. After it calls the print_x function (which was defined in a different global context), you can't expect print_x to know anything about the globals in exec's execution context -- print_x only knows the globals in it's module's context.

Sign up to request clarification or add additional context in comments.

4 Comments

Ok, thank you. So, I will need to define the print_x() function using exec? Is there any other way to change the namespace of a function?
@jordanwh if you really want to change the globals you could create a copy of the function with your own scope passed for the new functions globals.
@jordanwh -- I think I've seen some (maybe cpython specific) solutions that created a new function from and old one using types.FunctionType or something similar. I don't know how to do it off the top of my head so you'll probably need to do some sleuthing if you really want to try to make it work ...
@Tadhg McDonald-Jensen Perfect. Thank you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.