[issue16781] execfile/exec execution in other than global scope uses locals(), leading to undefined behavior

Terry J. Reedy report at bugs.python.org
Sat Dec 29 05:45:39 CET 2012


Terry J. Reedy added the comment:

I suppose you could say that I kicked that particular can over to the class doc ;-).

The fundamental problem with exec is that it is at least as complicated as Python, since it executes any legal python code, and in fact is even more complicated* because there are various possible relationships with the calling context. Moreover, it always returns None, so that *any* effect is a side-effect, which tends to be 'magical'.

* For one thing, people can write and run normal python code without knowing that a = b (and other binding statements, like import) at module scope means locals()['a'] rather than globals()['a']. At module scope, there are the same because globals() is locals(). Within exec'ed code, they may not be the same thing even for 'top level' code. This is exactly what tripped up Anatoly in his example with the import.

I am thinking that a short How To Exec() might be a good idea, since a real explanation is too much for even a half-page entry in the built-ins chapter.

Note: the following doc statement "Be aware that the return and yield statements may not be used outside of function definitions" needs to have nonlocal added.

>>> nonlocal a
SyntaxError: nonlocal declaration not allowed at module level
>>> exec('nonlocal a')
Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    exec('nonlocal a')
  File "<string>", line None
SyntaxError: nonlocal declaration not allowed at module level

>>> def f(): exec('nonlocal a') 

f()
...
SyntaxError: nonlocal declaration not allowed at module level

This again points to why exec can be confusing. compile() considers the string it compiles to be top-level code without any surrounding context. However, exec() enables one to run 'top level' code with different globals and locals. There is no exact precedent for this in normal operation. The closest is execution of code within a class statement (before the type(name, dic, bases) part). But even that is not absolutely the same for nonlocal (though this could be the only exception ;-).

>>> >>> class C: nonlocal a
SyntaxError: no binding for nonlocal 'a' found

A different error here (arguably not the best) -- the same as

>>> def f(): nonlocal a
SyntaxError: no binding for nonlocal 'a' found

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue16781>
_______________________________________


More information about the Python-bugs-list mailing list