[Python-Dev] variable name resolution in exec is incorrect (original) (raw)

Terry Reedy tjreedy at udel.edu
Wed May 26 19:40:43 CEST 2010


Mark Dickinson wrote (with interactice prompts removed)

code = """
y = 3 def f(): return y . f() """ exec code in {} # works fine exec code in {}, {} # dies with a NameError

Traceback (most recent call last): File "", line 1, in File "", line 4, in File "", line 3, in f NameError: global name 'y' is not defined

I verified that 3.1 (with exec adjusted to be a function) operates the same.

On 5/26/2010 8:51 AM, Nick Coghlan wrote:

exec with a single argument = module namespace exec with two arguments = class namespace

I verified in 3.1 that indenting 'code' and prepending 'class C():\n' gives the same error and that prepending 'def f():\n' now, with nexted function namespaces, does not give an error, although it would have been an error before Python 2.2, when there were no nested function namespaces.

On 5/26/2010 10:03 AM, Colin H wrote:

Thanks for the details on why the observed behaviour occurs - very clear. My only query would be why this is considered correct? Why is it running as a class namespace, when it is not a class?

You are expecting that it run as a function namespace (with post 2.2 nesting), when it is not a function. Why is that any better?

Is there any reason why this is not considered a mistake? Slightly concerned that this is being considered not a bug because 'it is how it is'.

In original Python, the snippet would have given an error whether you thought of it as being in a class or function context, which is how anyone who knew Python then would have expected. Consistency is not a bug.

When nested function namespaces were introduced, the behavior of exec was left unchanged. Backward compatibility is not a bug.

A change could have been proposed for 3.x, but I do not remember such a discussion and expect it would have been rejected. One can get the nested function behavior by doing what I did in the test mentioned above. One could easily write a nested_exec function to do the wrapping automatically.


In http://bugs.python.org/issue8824

I suggest that

"In all cases, if the optional parts are omitted, the code is executed in the current scope. If only globals is provided, it must be a dictionary, which will be used for both the global and the local variables. If globals and locals are given, they are used for the global and local variables, respectively. If provided, locals can be any mapping object."

be followed by

"If only globals is provided or if onedict is provided as both globals and locals, the code is executed in a new top-level scope. If different objects are given as globals and locals, the code is executed as if it were in a class statement in a new top-level scope."

to make the behavior clearer.

Terry Jan Reedy



More information about the Python-Dev mailing list