classification
Title: Problems when calling exec from a function
Type: behavior Stage:
Components: Interpreter Core Versions: Python 2.4, Python 2.5
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: amaury.forgeotdarc, sandberg
Priority: normal Keywords:

Created on 2008-09-25 15:10 by sandberg, last changed 2008-09-26 05:55 by sandberg. This issue is now closed.

Messages (4)
msg73795 - (view) Author: Erik Carstensen (sandberg) Date: 2008-09-25 15:10
When an exec statement called from a function f defines a top-level
function g, the body of g cannot access the top-level symbols defined by
the exec statement (which also happen to be the local variables of f).
Example:

x = 2
def f():
    exec "x = 1\ndef b(): return x"
    print b()
f()

An unqualified guess is that the mix of being top-level and being a
local variable, makes the symbol end up somewhere between locals() and
globals(). Example:

The problem causes real-life problems when I want to create a wrapper
function around execfile() to handle certain exceptions.
msg73799 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-09-25 16:10
Right. Nested scopes only work for statically compiled code; inside an
'exec' block, non-local variables are global.

In your case, I suggest to specify the context in which the code has to
execute:

x = 2
def f():
    g = globals().copy()
    exec "x = 1\ndef b(): return x" in g
    print eval("b()", g)

This prints 1, as you want it, and can still access names defined
outside the f() function. And this gives you more control on the symbols
available to the executed code.
Python does something very similar when it loads a module.

I don't think that this behaviour can ever change. Tentatively closing
as "won't fix".
msg73818 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-09-25 21:47
See also:

http://docs.python.org/dev/reference/executionmodel.html#interaction-
with-dynamic-features
msg73833 - (view) Author: Erik Carstensen (sandberg) Date: 2008-09-26 05:55
Thanks! Passing an explicit global namespace solves the problem and is
something I wanted to do anyways, when I think about it.
History
Date User Action Args
2008-09-26 05:55:53sandbergsetmessages: + msg73833
2008-09-25 21:47:13amaury.forgeotdarcsetmessages: + msg73818
2008-09-25 16:10:48amaury.forgeotdarcsetstatus: open -> closed
resolution: wont fix
messages: + msg73799
nosy: + amaury.forgeotdarc
2008-09-25 15:10:20sandbergcreate