1

With this test code using exec (using Python 3.4):

vals = {}
exec('def fun(): print("Hello from fun")', vals)
exec('def main(): fun()', vals)
vals['main']()

The output is:

Hello from fun

But I did not expect this to work, since I assumed that fun and main where interpreted as separate code pieces without a common namespace to resolve the reference in main to fun.

So how can execution of main resolve the reference to fun?


Addition based understanding the issue. With print of id for vals and globals, it becomes clear that the two functions sees the same globals:

vals = {}
print('id(vals):', id(vals))
exec('def fun(): print("fun id(globals()):", id(globals())); print("Hello from fun")', vals)
exec('def main(): print("main id(globals()):", id(globals())); fun()', vals)
vals['main']()

Which gives:

id(vals): 32271016

main id(globals()): 32271016

fun id(globals()): 32271016

Hello from fun

So the vals is used as globals for the code in exec, thus giving the connection, as @Dunes and other comments described. Thanks.

5
  • 4
    Through vals, which you explicitly provided. See e.g. docs.python.org/2/reference/simple_stmts.html#exec Commented Feb 27, 2015 at 12:52
  • It might be helpful to add print vals after each exec line. Commented Feb 27, 2015 at 12:58
  • 4
    @jonrsharpe I'm guessing the OPs actually after docs.python.org/3.4/library/functions.html#exec - where exec is a function and not a statement... Commented Feb 27, 2015 at 12:59
  • @JonClements ah, perhaps, but the same syntax works in both! Commented Feb 27, 2015 at 13:57
  • @jonrsharpe that's True :p Commented Feb 27, 2015 at 13:58

1 Answer 1

3

By providing vals to both exec functions, you have provided the common namespace. The second argument to exec is a dictionary to use for global references in any code that is executed. When the first statement is executed it creates fun and stores it in the global namespace (vals). Thus, when when main tries to find fun, it finds that it is not a local variable and so tries to lookup fun in its globals (which is also vals). Since fun exists in vals the lookup works and the function retrieved and called. If gave each exec its own dict then this wouldn't work. If you don't provide vals then the current globals that exec is called in is used as the globals (so this would still work).

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.