exec(), execfile() and local-variable binding?

Jonathan jonaomi at excite.com
Sat Aug 9 19:19:27 EDT 2003


I'm puzzled by Python's behavior when binding local variables which
are introduced within exec() or execfile() statements. First, consider
this simple Python program:

# main.py
def f() :
        x = 1
        print "x:", x
f()

This just prints "x: 1" when run. Now, what happens if we move the
assignment into a separate file "assign.py", and attempt to read it in
with execfile()?

# assign.py
x = 1
print "x in assign.py:", x

# main_execfile.py
def f () :
        execfile("assign.py")
        print "x in main_execfile.py:", x
f()

So, you might assume that if execfile() worked like a C-style
#include, this would work fine. But it doesn't. Instead, when
"main_execfile.py" is compiled, the "x = 1" assignment in "assign.py"
is never seen, so the 'x' in the print statement is assumed to be a
global variable. Then at run-time, we get an error about 'x' being an
undefined global variable:

x in assign.py: 1
x in main_execfile.py:
Traceback (most recent call last):
  File "main_execfile.py", line 4, in ?
    f()
  File "main_execfile.py", line 3, in f
    print "x in main_execfile.py:", x
NameError: global name 'x' is not defined

Well, that's understandable. But what I find strange is that exec()
*doesn't* work in this way. Consider this version:

# main_exec.py
def f() :
        exec("x = 1")
        print "x:", x
f()

I would have thought that, just like the execfile() version, the "x =
1" string would not be interpreted at parse-time, so that the 'x' in
the "print" statement would again be taken to be a global variable.
But no, this version runs fine, producing the output "x: 1".

And this fancier version also runs:

# main_exec2.py
def f(v) :
        exec(v + " = 1")
        print "x:", x
print "Type 'x':"
f(input())

Here, if the user enters 'x', the assignment string "x = 1" is made
up, and the program runs as before.

So, why do these exec() versions work, when the execfile() one didn't?
Specifically, why aren't the 'x' variables in the "print" statements
taken as global variables? AFAIK, this should be a compile-time
decision, but the "x = 1" assignment strings can't have been
interpreted at that time.

Thanks for any help,

-- Jonathan




More information about the Python-list mailing list