exec throws an exception...why?

Nick Jacobson nicksjacobson at yahoo.com
Mon Jun 7 03:37:46 EDT 2004


Thank you very much for the detailed response.  But there's still a
problem.

> The name binding in assignment seems to proceed only for locals,
> unless a variable is declared as global explicitly. That is, by
> default, the supplied global dictionary is read-only, unless the
> 'global' statment is used explicitly for those variables that you want
> to override.

Agreed.  The global dictionary is not modified.

But here's the thing.  From the Python Ref. Manual:

"If the [local variable] definition occurs in a function block, the
scope extends to any blocks contained within the defining one..."

So as long as code is not on the module level, scopes are extended. 
e.g. this works fine:

def main():
	y = 3
	def execfunc():
		print y
	execfunc()
if __name__ == '__main__':
	main()

But, the following code fails, saying that y is undefined:

def main():
	s = \
"""
y = 3
def execfunc():
	print y
execfunc()
"""
	d = {}
	e = {}
	exec s in d, e

if __name__ == '__main__':
	main()

Why not?  Because it doesn't realize it's in main()!  It thinks it's
on the module level! (I guess the indentation is a clue.)

Now, if it WERE simply code on the module level, it would also work:

y = 3
def execfunc():
	print y
execfunc()

because as you explained, y goes in globals().  This is probably why
the scopes don't nest at this level: they normally don't need to.

Conclusion:

Is code from the exec statement on the module level or not?  It
doesn't get its locals mapped to globals.  But it also doesn't get its
local variables nested.  So it gets neither benefit.  IMO it should
get one or the other.  i.e. the second piece of code should work.

--Nick



More information about the Python-list mailing list