Stephen Hansen wrote: >Hendrik van Rooyen wrote:
>>IDLE 1.1.3 ==== No Subprocess ==== >>>>> help(exec) >>SyntaxError: invalid syntax >>>>> >>Its the same under Linux SuSe, Python 2.5.1. >> >>I think this is a BUG. > >Exec is a statement, not a function nor an object: even though you can enclose parens around its arguments like you do later on, they >don't have any syntax meaning This is actually not correct - it is the root cause of my trouble. if you write, in a nested scope: exec ( "somestring to execute" in globals(),locals()) You get the syntax error, as the interpreter somehow sees it as one, unqualified thing. I did this, and it did not work in my real code, and that is why I started putting together the little example - all the trouble caused by too many parenthesis. But it is a GoodThing I made the error, because it has taught me more about how the scopes work. > >You can't help(print) or help(import) either. Right - was not aware of this - I suppose it has never occured to me to ask for help on print or import. >>Anyway, my real problem looks like this: >>>>> def Somefunc(): >> def excrescence(): >> exec('BUILD = "someString"') >> return BUILD >> >>SyntaxError: unqualified exec is not allowed in function 'excrescence >>it is a nested function (<pyshell#11>, line 3) >>>>> >> >>Now this works if it is not nested, and it works if it is a method in a class. >>Why the complaint about the nestedness? >> >> >Once upon a time, Python had only two scopes or namespaces: local and globals. It'd look up variables in the local scope and if it didn't >find them, it'd look them up in the global scope. (There's also the builtin namespace but to not digress...) 8<----------------------- historic position ---------------- > >Then PEP227 came around to add nested scopes -- or lexical scopes. Its what made "nested" functions like that actually useful: it's what >brought closures into the scenario. As of Python 2.2, within bar() it would be able to see the definition of a because namespaces can >now be nested. > >This addition was a problem for a couple features: doing "from blah import *" within a function, and a bare exec (an exec without an >explicit globals() and locals()) that happened in certain places-- in this case a nested function. They introduced that SyntaxError to make >sure it wouldn't accidentally hit you. Read up on PEP227 for the full details. > Thanks - will do, but I think I am already getting the picture. >To get around this, you need to specify exactly what scope you want exec to happen in when you're in a place where the 'current' scope >is nested. You qualify exec-- > Right - and it also works if you simply use the current locals() in the global position. I suppose one should use the scope "one up" in globals, and locals() as locals, but I can't figure out how to do that directly. (I mean using Somefunc'c locals() as the global for the exec, and excrescence's locals() as the locals - would require keeping a reference - see below) > >>So there is some namespace thing happening that is too subtle for me, and I >>would like to know what "unqualified" means in the above message, and >>what one must do to "qualify" the statement, if that is what is needed. >> > >by doing: > > exec code in <global dictionary>, <local dictionary> > >In your situation: > > >>> def Somefunc(): > def excrescence(): > exec "BUILD = 'someString'" in globals(), locals() > >is probably sufficient. globals() returns the dictionary of the global namespace, locals() the dictionary of the current functions (non->nested) namespace. > This works, thank you. However, locals() give you the nested function's namespace. The following illustrates what is going on: >>> def Somefunc(): print 'in Somefunc:',locals,id(locals),id(locals()) def excrescence(): print 'in excrescence:',locals,id(locals),id(locals()) exec "BUILD = 'someString'" in locals() print 'in excrescence:',locals,id(locals),id(locals()) return BUILD foo = excrescence() print 'in Somefunc:',locals,id(locals),id(locals()) return foo >>> Somefunc() in Somefunc: <built-in function locals> 7599848 18705696 in excrescence: <built-in function locals> 7599848 18799040 in excrescence: <built-in function locals> 7599848 18799040 in Somefunc: <built-in function locals> 7599848 18705696 'someString' >>> This leads me to speculate into other evil ways - if I use the outer locals, I need not even return the thing, it would get defined: >>> def Somefunc(): print 'in Somefunc:',locals,id(locals),id(locals()) outer_locals = locals() def excrescence(): print 'in excrescence:',locals,id(locals),id(locals()) exec "BUILD = 'someString'" in outer_locals print 'in excrescence:',locals,id(locals),id(locals()) return None foo = excrescence() print 'in Somefunc:',locals,id(locals),id(locals()) return BUILD >>> Somefunc() in Somefunc: <built-in function locals> 7599848 18822032 in excrescence: <built-in function locals> 7599848 18619824 in excrescence: <built-in function locals> 7599848 18619824 in Somefunc: <built-in function locals> 7599848 18822032 'someString' >>> And so it does. Using the locals like this in the globals position is not a good idea, except for purposes of illustration, like here - if one actually prints the contents of the dict after the exec, you see what is meant by namespace pollution.... Thank you to all who have responded - I think I have it now - Hendrik -- http://mail.python.org/mailman/listinfo/python-list