Bugs item #991196, was opened at 2004-07-14 21:30 Message generated for change (Comment added) made by gbrandl You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=991196&group_id=5470
Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: Python Interpreter Core Group: Python 2.3 Status: Open Resolution: None Priority: 5 Submitted By: Nick Jacobson (nickjacobson) Assigned to: Nobody/Anonymous (nobody) Summary: An inconsistency with nested scopes Initial Comment: There's an inconsistency with nested scopes. >From the Python Ref. Manual: "If [a local variable] definition occurs in a function block, the scope extends to any blocks contained within the defining one..." i.e. So as long as code is not on the module level, scopes are extended. Therefore this works: def main(): y = 3 def execfunc(): print y execfunc() if __name__ == '__main__': main() In addition, if code IS on the module level, its variables go in globals(). So this works too: y = 3 def execfunc(): print y execfunc() However, (here's the inconsistency) 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() In this case, the code in s is treated like it's on the module level, and the nested scope treatment of y doesn't occur. BUT, unlike normal code on the module level, y doesn't go in globals(). I think globals() is locked or something? Conclusion: The latter piece of code should work; that is, y should be nested and therefore recognized by execfunc(). ---------------------------------------------------------------------- >Comment By: Georg Brandl (gbrandl) Date: 2006-02-20 22:06 Message: Logged In: YES user_id=849994 Closed #1167300 as a duplicate. ---------------------------------------------------------------------- Comment By: Armin Rigo (arigo) Date: 2004-08-07 21:59 Message: Logged In: YES user_id=4771 The behavior you get can be explained quite easy, but it seems nevertheless inconsistent with the documentation: in my opinion it is a serious bug. The reason the "exec"ed code doesn't work like the same code put at the global module level is that code that runs at the module level always runs with the same dictionary for its globals and locals, whereas in your example you use two different dictionaries. Assignments always go to the locals; that's why 'y' goes into the dictionary 'e'. Now a function can only see its own locals and the surrounding globals; that's why execfunc() misses the value of 'y'. This is the old way Python worked. In recent versions, a special trick was added so that functions defined inside another function find variable bindings from the enclosing function. I think you found a case where this trick fails to apply. ---------------------------------------------------------------------- Comment By: Josiah Carlson (josiahcarlson) Date: 2004-07-22 16:55 Message: Logged In: YES user_id=341410 >>> def f(): ... y = 5 ... print 'y' in globals(), 'y' in locals() ... def i(): ... print 'y' in globals(), 'y' in locals() ... i() ... >>> f() False True False False >>> >>> def g(): ... gl = {};lo={} ... exec '''y = 5 ... print 'y' in globals(), 'y' in locals() ... def i(): ... print 'y' in globals(), 'y' in locals() ... i() ... ''' in gl, lo ... >>> g() False True False False That looks constant...but what if we print out 'y'? >>> def s(): ... y = 5 ... print 'y' in globals(), 'y' in locals(), y ... def i(): ... print 'y' in globals(), 'y' in locals(), y ... i() ... >>> s() False True 5 False True 5 >>> >>> def t(): ... gl = {};lo = {} ... exec '''y = 5 ... print 'y' in globals(), 'y' in locals(), y ... def i(): ... print 'y' in globals(), 'y' in locals(), y ... i() ... ''' in gl, lo ... >>> t() False True 5 False False Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in t File "<string>", line 5, in ? File "<string>", line 4, in i NameError: global name 'y' is not defined Now why did 'y' stick itself into the locals() of i() in s()? Is this another bug? What if we remove the namespaces gl and lo? >>> def u(): ... exec '''y = 5 ... print 'y' in globals(), 'y' in locals(), y ... def i(): ... print 'y' in globals(), 'y' in locals(), y ... i() ... ''' ... >>> u() False True 5 False False Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 2, in u File "<string>", line 5, in ? File "<string>", line 4, in i NameError: global name 'y' is not defined Nope, still dies. It does seem to be a bug in exec. I'm still curious why 'y' was placed into i()'s local namespace in s(). ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=991196&group_id=5470 _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com