Path: csiph.com!usenet.pasdenom.info!aioe.org!news.stack.nl!newsfeed.xs4all.nl!newsfeed2.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.001 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'cpython': 0.05; 'mrab': 0.05; 'class,': 0.07; 'exec': 0.07; 'variables.': 0.07; 'python': 0.09; 'assigning': 0.09; 'dict': 0.09; 'globals': 0.09; 'messing': 0.09; 'modifies': 0.09; 'namespace': 0.09; 'returns,': 0.09; 'subject:Python3': 0.09; 'variables,': 0.09; "wouldn't": 0.11; 'suggest': 0.11; 'times,': 0.13; 'useful,': 0.13; 'essential': 0.15; '"python': 0.16; "'),": 0.16; 'both.': 0.16; 'hint': 0.16; 'it),': 0.16; 'local.': 0.16; 'losing': 0.16; 'scope.': 0.16; 'suggestion.': 0.16; 'syntax.': 0.16; 'tripped': 0.16; 'wrote:': 0.17; 'module,': 0.17; 'variables': 0.17; 'thanks,': 0.18; '>>>': 0.18; 'feb': 0.19; 'changes': 0.20; 'bit': 0.21; 'meant': 0.21; 'assignment': 0.22; 'keys': 0.22; 'modifying': 0.22; 'names.': 0.22; 'visible': 0.22; "i'd": 0.22; 'work.': 0.23; "i've": 0.23; 'seems': 0.23; 'testing': 0.24; 'pass': 0.25; 'tried': 0.25; 'header:In-Reply-To:1': 0.25; 'header:User-Agent:1': 0.26; '(which': 0.26; 'values': 0.26; 'ago': 0.27; 'am,': 0.27; 'skip:e 30': 0.27; "doesn't": 0.28; 'dictionary': 0.29; 'surprised': 0.29; 'definition': 0.29; 'no,': 0.29; 'points': 0.29; 'skip:_ 10': 0.29; "i'm": 0.29; 'e.g.': 0.30; 'saves': 0.30; 'function': 0.30; 'error': 0.30; 'code': 0.31; 'url:python': 0.32; 'not.': 0.32; 'could': 0.32; 'docs': 0.33; 'problem': 0.33; 'to:addr:python- list': 0.33; 'know.': 0.33; 'point.': 0.33; 'hi,': 0.33; 'changed': 0.34; 'thanks': 0.34; 'doing': 0.35; "won't": 0.35; 'something': 0.35; 'add': 0.36; 'really': 0.36; 'but': 0.36; 'url:org': 0.36; 'url:library': 0.36; "didn't": 0.36; 'anything': 0.36; 'should': 0.36; 'itself': 0.37; 'does': 0.37; 'why': 0.37; 'subject:: ': 0.38; 'copying': 0.38; 'mean': 0.38; 'object': 0.38; 'some': 0.38; 'url:docs': 0.38; 'sure': 0.38; 'several': 0.39; 'to:addr:python.org': 0.39; 'received:192': 0.39; 'notice': 0.39; 'received:192.168': 0.40; 'your': 0.60; 'real': 0.61; 'free': 0.61; 'back': 0.62; 'necessarily': 0.63; 'more': 0.63; 'within': 0.64; 'below.': 0.68; 'restore': 0.69; 'received:74.208': 0.71; 'transfer': 0.76; '4th': 0.78; 'subject:this': 0.84; '2013': 0.84; 'dict.': 0.84; 'everything.': 0.84; 'game,': 0.84; 'locals': 0.84; 'presumably': 0.84; 'url:functions': 0.84; 'concluded': 0.91; 'dozens': 0.91; 'forgotten': 0.91; 'net.': 0.91; 'angel': 0.93 Date: Tue, 12 Feb 2013 10:40:18 -0500 From: Dave Angel User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130106 Thunderbird/17.0.2 MIME-Version: 1.0 To: python-list@python.org Subject: Re: Python3 exec locals - this must be a FAQ References: <511a51b3$0$3111$ba620e4c@news.skynet.be> In-Reply-To: <511a51b3$0$3111$ba620e4c@news.skynet.be> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Provags-ID: V02:K0:9cH3x6kC+5BPiwI87loI0xYlqj/J/8/9JfUH/8XdGsn JS0NcU6eUotsPm2FptjkAXaB+Km4ubjwg3SLmHUZfVombVTkZS Vd/7FClopF3VcGXKkyyxYnDW1OXDTE/d5ZPEyDatePugHrC+zd eVYuMUYO0e+dJwcbl2YLkhp+ILvhMPcg+NSd2OUS8+cBT0ySl9 diQydw487UermMBmSOP9qXRpktDgy7DS4VTUVcYkdQ1ajHw3t1 nUXOykoRqSYyn9cseZvVg6Nyr7clqJD1W6OWfdtB3FVcWUA6qQ D4r7dDxdbgQA0L+qhU6ODu5H7FkpjkvLhYeN7kWA5hfA3YkdQ= = X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 98 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1360683643 news.xs4all.nl 6961 [2001:888:2000:d::a6]:42568 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:38762 On 02/12/2013 09:29 AM, Helmut Jarausch wrote: > On Tue, 12 Feb 2013 08:27:41 -0500, Dave Angel wrote: > >> On 02/12/2013 06:46 AM, Helmut Jarausch wrote: >>> Hi, >>> >>> I've tried but didn't find an answer on the net. >>> >>> The exec function in Python modifies a copy of locals() only. >>> How can I transfer changes in that local copy to the locals of my >>> function ** without ** knowing the names of these variables. >>> >>> E.g. I have a lot of local names. >>> >>> Doing >>> >>> _locals= locals() >> >> This doesn't copy everything. But perhaps you know that and you're just >> testing us. > > No, I didn't know. And I'm bit surprised since this is recommend > several times, e.g. in "Python Essential Reference, 4th ed" by > David Beazley. > That assignment is useful, because it presumably saves the time that calling locals() will take constructing the dict. But copying anything by assignment just makes a new reference to the same thing. If that thing is mutable, as a dict is, then changes made to the (dict) object are visible to both. >> >>> expr=compile(input('statements assigning to some local variables '), >>> 'user input','exec') >>> exec(expr,globals(),_locals) >>> >>> How can I "copy" the new values within _locals to my current locals. >>> >>> If I knew that Var1 has changed I could say Var1 = _locals['Var1'] >>> but what to do in general? >> >> locals()["Var1"] = _locals["Var1"] will set the same Var1 local. > > Thanks for this hint which surprises me again since I thought > locals() by itself is a copy only. > (Thanks MRAB for your correction.) As MRAB points out, I was in error on this point. I only tested it in global scope. Inside a function it doesn't seem to work. See docs below. >> >> So you might write a loop on _locals. >> >> But beware if someone has deleted one of the "variables" it may not do >> what you'd like. You cannot necessarily add back a local with the above >> syntax. > > Does this mean that adding something completely new won't work? > > Many thanks, > Helmut. > That depends. All I can say for sure is it won't work for CPython to create new local variables inside a function that way. It seems to work for globals (which are also locals when code of global scope is using it), but I wouldn't count on it. http://docs.python.org/2/library/functions.html#locals Note the sentence: """The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter""" Notice that adding or removing items from a dictionary is modifying it, while changing values that the keys are associated with is not. But apparently the documentation meant it more strictly than it was worded. If you really have dozens of "variables" that you want to pass to exec, then restore their original values after it returns, I suggest you make your own (empty) class, and use that as a namespace to accomplish it. The reason I was tripped up on this definition is that I've concluded long ago that messing with locals() is a losing game, so I'd forgotten some of the subtlety. If we knew what the real problem was, we might have a suggestion. For example, if the intent is for the exec to work with a copy of the variables, without affecting the originals, then why not use the copy module, and pass the *copy* to the exec logic. -- DaveA