470,631 Members | 1,702 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,631 developers. It's quick & easy.

Exec Statement Question

I'm curious why this code isn't working how I expect it to:

import sys
d=3

def func1(a,b,c):
print a,b,c,d
print sys.path

exec "func1(1,2,3)" in {'func1':func1}

----
returns:
1 2 3 3
[ sys.path stuff ....]

Since I'm telling exec to operate only within the context of the
dictionary I give it, why does it still see sys.path and d? I figured
it would throw a NameError.

Is there a way to call exec such that it won't have access to any more
objects than I explicitly give it?

Thanks,

Greg
Apr 9 '07 #1
4 2038
On Apr 8, 11:31 pm, "Gregory Piñero" <gregpin...@gmail.comwrote:
I'm curious why this code isn't working how I expect it to:

import sys
d=3

def func1(a,b,c):
print a,b,c,d
print sys.path

exec "func1(1,2,3)" in {'func1':func1}

----
returns:
1 2 3 3
[ sys.path stuff ....]

Since I'm telling exec to operate only within the context of the
dictionary I give it, why does it still see sys.path and d? I figured
it would throw a NameError.

Is there a way to call exec such that it won't have access to any more
objects than I explicitly give it?

Thanks,

Greg
I think the way it works is that when the def is parsed, a function
object is created and assigned to the name func1. When the function
object is created, d is "bound" to the global value 3, while a,b,c lie
in wait for arguments to land in their gullets like venus fly traps.
Your dictionary has a key whose value is a reference to the function
object, which already has the value 3 bound to d.
Apr 9 '07 #2
Gregory Piñero <gr********@gmail.comwrote:
I'm curious why this code isn't working how I expect it to:

import sys
d=3

def func1(a,b,c):
print a,b,c,d
print sys.path

exec "func1(1,2,3)" in {'func1':func1}

----
returns:
1 2 3 3
[ sys.path stuff ....]

Since I'm telling exec to operate only within the context of the
dictionary I give it, why does it still see sys.path and d? I figured
it would throw a NameError.

Is there a way to call exec such that it won't have access to any more
objects than I explicitly give it?
func1 accesses its globals through func1.func_globals (which you can't
reassign -- it's a read-only attribute).

You may make a new function object w/ a different globals dict...:
>>g = type(func1)(func1.func_code, {})
and that will fail (even when called directly, but similarly if exec'd)
as it's missing key 'd' in its globals:
>>g(1, 2, 3)
1 2 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in func1
NameError: global name 'd' is not defined
The globals dict you pass to exec is the globals at the time of CALL,
not the globals seen from INSIDE func1; that's always going to be the
func_globals attribute of the function object, so you need to control
that (by suitably building a new function object as you require).
Alex
Apr 9 '07 #3
7stud wrote:
On Apr 8, 11:31 pm, "Gregory Piñero" <gregpin...@gmail.comwrote:
Is there a way to call exec such that it won't have access to any more
objects than I explicitly give it?

I think the way it works is that when the def is parsed, a function
object is created and assigned to the name func1. When the function
object is created, d is "bound" to the global value 3, while a,b,c lie
in wait for arguments to land in their gullets like venus fly traps.
Your dictionary has a key whose value is a reference to the function
object, which already has the value 3 bound to d.
Not exactly. As Georg Brandl said, the function has a reference to the
*globals* currently in use when it was defined, not directly to the
name "d".

To the OP: If you want a function with almost "empty" globals, compile
it the same way you used to execute it:
>>text = """def func1(a):
.... print a
.... print b
....
.... func1(3)
.... print func1.func_globals.keys()
.... """
>>>
exec text in {}
3
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<string>", line 5, in ?
File "<string>", line 3, in func1
NameError: global name 'b' is not defined
>>exec text in {"b": 123}
3
123
['__builtins__', 'func1', 'b']
>>>
I said *almost* empty because Python may insert other keys into the
globals, like __builtins__ above (see http://docs.python.org/ref/exec.html)

--
Gabriel Genellina

Apr 9 '07 #4
Thanks for the responses everyone. That does make sense to me now.

-Greg

Apr 10 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by Toby Donaldson | last post: by
5 posts views Thread by Carlos Ribeiro | last post: by
1 post views Thread by Andr? Roberge | last post: by
5 posts views Thread by TPJ | last post: by
7 posts views Thread by gregory.lielens | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.