Repost: execfile() confusion

Steve Holden sholden at holdenweb.com
Fri Sep 28 21:35:15 EDT 2001


"Nathaniel Gray" <n8gray at caltech.edu.is.my.e-mail.address.com> wrote in
message news:9p2iuk$1au at gap.cco.caltech.edu...
> Sorry for the repost but I didn't get any responses.
> So once again, execfile() isn't doing what I thought it did.
>
Please accept my aplogies, I was getting on with my life under the confident
assumption that the many fine brains who read this newsgroup would assist
you with lightning speed. Since they've *all* let you down (shame on you,
you know who you are), I'll have to resort to my standard strategy of
providing an incorrect explanation and then letting the rest of c.l.py tell
you exactly why I am wrong.

> For example, with these two files:
>
> ##############
> #### test2.py ####
> x = 'spam'
>
> #### test.py ####
> def doit():
>     execfile( 'test2.py' ) # x = 'spam'
>     print x
>
> doit()
> ##############
>
> I get the following when I run 'python test.py':
> """
> Traceback (most recent call last):
>   File "test.py", line 5, in ?
>     doit()
>   File "test.py", line 3, in doit
>     print x
> NameError: global name 'x' is not defined
> """
>
> I though that execfile was supposed to act on the locals() of the scope
> from which it was called.  I also tried adding x=None to the top of doit()
> but execfile still doesn't change its value to 'spam'.  Can somebody
please
> explain what's going on?
>
You have made a mistaken assumption, mistrusting the documentation when in
fact everything is perfectly explicable as documented. Your assumption is
that inside doit() the interpreter will check for x as a local before it
checks for x as a global.

Unfortunately this is NOT the case, and the error mesage explicitly informs
you of that fact. When it compiles a function, the interpreter statically
examines the code for assignments to (or more accurately, bindings of)
names. If any are found then it compiles code to access those names as
locals. The situation is slightly complicated if you have imported
nested_ascopes from future, as it then statically examines each lexically
surrounding function before defaulting to module global, but that need not
concern us here.

The error message is explicitly telling you that the global x has no value.
So, Watson, the only theory that fits the facts is that execfile() has
behaved exactly as its documentation describes, and bound the value 'spam'
to the name x in the local scope of function doit().

Because there are no bindings to x in doit() to be found by static
examination, however, the interpreter has decided that x will be in the
module's global scope, and compiled bytecode which attempts to access it
form there. Which, you will now realise, is why the error message complains
that global x has not been defined.

So now, Watson, if you will be good enough to hand me my violin and my
cocaine, you can return to your scratchings, and I shall return to mine.
Kindly insert a print of the dir() function inside doit(), and return only
if no x is to be found therein.

never-seen-a-case-for-a-local-statement-before-ly y'rs  - steve
--
http://www.holdenweb.com/








More information about the Python-list mailing list