2

I need to execute some dynamically generated code in Python and ensure that this code will have access to some custom global values, for example 'bar'. Based on python documentation i assembled the following test code:

def foo() : print( globals() )
exec "foo()" in dict( globals(), bar = 1 )

According to documentation, calling foo() from exec with bar added to scope will list bar among globals() inside foo() body. But the actual output is:

{'__builtins__': <module '__builtin__' (built-in)>, '__file__': 'C:\\Users\\Eye\
\Documents\\first.py', '__package__': None, '__name__': '__main__', 'foo': <func
tion foo at 0x01DD40F0>, '__doc__': None}

No bar here :(. How to make bar accessible from within code executed in exec?

2
  • @NiklasB. Why not? Did you try it? It is perfectly valid to have an expression (globals()) and print that. Commented Mar 7, 2012 at 13:08
  • @glglgl: Hm, I guess you're right :) Still, this is not really good style, IMHO. Commented Mar 7, 2012 at 13:12

4 Answers 4

3

(I'm skipping here a usual rant about how generally bad and insecure is exec)

If you try this:

exec "print globals().get('bar')" in dict( globals(), bar = 1 )

you will see that it works as expected.

When you define a function, it's bound with it's module's namespace, that's what it sees as globals. You can reach those bindings via foo.func_globals. That's how a function can access module internals via globals, but cannot see the caller's environment (where bar is defined).

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

2 Comments

I can't see foo.func_globals to contain bar either :(. My point is to call external function from exec, not just a bare print.
That's the whole point, foo.func_globals is what globals() returns, and that's fixed at the foo compilation time. bar is defined in the calling context and you cannot access it from the function without some deep magic. That's the same as when you call foo from other_module.baz having bar an other_module's global.
2

According to the documentation, when globals() is called from within a function it returns the dictionary for the module in which the function was defined.

If you create the new global AND pass it as an argument, you should be able to call functions dynamically. For example,

def foo(bar):
  print bar

exec "foo(bar)" in dict(globals(), bar = "hello")

4 Comments

If i change the code to just access global object bar it will be "undefined".
The issue is that once foo is defined its globals are fixed. The new variables you pass in are only available within the quoted part of the exec statement, in this case "foo(bar)". I think you may only be able to do it if you pass the new variables as arguments to the function.
Am i correct what it's not important what i'm supplying in dictionary after in keyword - functions outside exec quotes will not be able to access this information?
The code inside the quotes will be able to access the new globals in the dictionary, but any functions you call will use the globals that were there when the function was defined. In order to pass new variables to these functions you will need to pass them as arguments.
0

sorry, what is the problem with this?

def foo() : print( globals() )
bar = 1
exec "foo()"
{'bar': 1, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', 'foo': <function foo at 0x7fd1b3954ed8>, '__doc__': None}

1 Comment

The problem is that OP wants to provide custom globals to the function, which would require nasty hacks, as far as I know.
0

I have found a suitable solution:

def foo() : print( foo.bar )
exec "foo.bar = bar\n" + "foo()" in dict( globals(), bar = 1 )

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.