[Python-Dev] Inconsistent nesting of scopes in exec(..., locals())

2010-04-23 Thread Joachim B Haga
There seem to be an inconsistency in the handling of local scopes in
exec. Consider the following code, which raises NameError if the '#' is
removed from the second last line.


block = """
b = 'ok'
def f():
print(b)# raises NameError here
f()
"""
scope = locals()#.copy()
exec(block, globals(), scope)


The intermediate scope is searched for the variable name if the third
argument to exec() is locals(), but not if it is locals().copy().
Testing further, it looks like NameError is raised for any dict which 
is not identically equal to either globals() or locals().

This behaviour is quite unexpected, and I believe it qualifies as a 
bug. Tested with python 2.6.5 and 3.1.2.

-- 
Joachim B Haga

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Inconsistent nesting of scopes in exec(..., locals())

2010-04-23 Thread Joachim B Haga
Nick Coghlan  writes:

> Joachim B Haga wrote:
>> There seem to be an inconsistency in the handling of local scopes in
>> exec. [...]
>> 
>> The intermediate scope is searched for the variable name if the third
>> argument to exec() is locals(), but not if it is locals().copy().
>
> What actually matters is whether or not the first and second scope are
> the same dictionary or not.
>
> If they're different, then the supplied local scope is treated as
> equivalent to a class definition scope, and hence won't participate in
> lexical scoping. If they're the same (which happens implicitly if the
> second one is omitted) then they're treated as a module scope (and hence
> written values are visible as globals inside any defined functions).

Ok, thank you for the explanation.

> Since changing this would break class definitions, that ain't going to
> happen. Suggestions for how to explain the behaviour more clearly in the
> exec() documentation probably wouldn't hurt though.

I don't quite see how exec() affects the class definition syntax?
Anyhow, I definitely agree that this should be documented. I 
suggest the following (condensed from your explanation):

-If provided, /locals/ can be any mapping object.
+If provided, /locals/ can be any mapping object. It is treated as
equivalent to a class definition scope, and hence does not participate
in lexical scoping.

-- 
Joachim B Haga

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com