Repost: execfile() confusion

Nathaniel Gray n8gray at caltech.edu.is.my.e-mail.address.com
Sun Sep 30 03:05:44 EDT 2001


Steve Holden wrote:
> "Nathaniel Gray" <n8gray at caltech.edu.is.my.e-mail.address.com> wrote
>> [snip code]
>> 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.
>
> [snip explanation of compiler's analysis]

The compiler don't enter into it.  <0.7 wink>  Well really it does, somewhat, 
but it's not actually the problem.  I suspected that the compiler's analysis 
was the problem and this is why I mentioned that I tried adding x=None to the 
top of doit().  This was to force the compiler to recognize x as a local 
variable.  Unfortunately, in that case the assignment in test2.py has no 
effect.  Here's a slightly modified version of the files that will perhaps make 
my confusion clear:

#### test2.py ####
print 'test2 locals:', locals().keys()
x = 'spam'
print 'Post-assignment test2 locals:', locals().keys()

#### test.py ####
def doit():
    joe = 99
    #x = 'not spam'  # THE MAGIC LINE
    execfile( 'test2.py' ) # x = 'spam'
    print 'x is now: %(x)s' % locals()   #No compiler tricks allowed!
doit()

Trial 1.  Here's the output with the "magic" line commented:
        test2 locals: ['joe']
        Post-assignment test2 locals: ['x', 'joe']
        x is now: spam

Trial 2.  And when you uncomment it:
        test2 locals: ['joe', 'x']
        Post-assignment test2 locals: ['joe', 'x']
        x is now: not spam

I just can't seem to find a consistent story here.  Clearly the assignment is 
happening in the locals() of test2 as evidenced by the post-assignment 
printout.  Clearly the locals() of test2 should be the same as the locals() of 
test, as evidenced by the fact that 'joe' shows up in test2's locals() and the 
fact that 'x' shows up in doit()'s locals in trial 1.  Sorry, Sherlock, but 
this is just nucking futs!  ;^)  Python seems to be waffling over whether or 
not the assignment to x in test2.py does or does not happen in doit()'s 
locals() based on whether x was *already* in doit()'s locals()!  

By the way, this behavior is the same in Python 1.4, so if it's a bug it's an 
old one.  Maybe there's a rational explanation for this, maybe it's a bug, or 
maybe it's just a place on the Python map labeled "here there be monsters", but 
in any case I'd sure like to understand it.  Maybe this is the excuse I've been 
waiting for to dip into Python's guts...

Thanks for your help,
-n8

-- 
Nathaniel Gray

California Institute of Technology
Computation and Neural Systems
--




More information about the Python-list mailing list