grigoryvp
grigoryvp

Reputation: 42463

Python: how to use 'exec' with custom scope?

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?

Upvotes: 2

Views: 2393

Answers (4)

grigoryvp
grigoryvp

Reputation: 42463

I have found a suitable solution:

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

Upvotes: 0

Ben Russell
Ben Russell

Reputation: 1423

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")

Upvotes: 2

bereal
bereal

Reputation: 34272

(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).

Upvotes: 3

bpgergo
bpgergo

Reputation: 16037

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}

Upvotes: 0

Related Questions