From: Peter on
I am puzzled by what appears to be a scope issue - obviously I have
something wrong :-)

Why does this work:

if __name__ == 'main':
execfile('test-data.py')
print data

and yet this doesn't (I get "NameError: global name 'data' not
defined"):

def X():
execfile('test-data.py')
print data

where test-data.py is:

data = [1,2,3,4]

I checked help on execfile and could only find the following
(mystifying) sentence:

"execfile() cannot be used reliably to modify a function’s locals."

Thanks
Peter
From: MRAB on
Peter wrote:
> I am puzzled by what appears to be a scope issue - obviously I have
> something wrong :-)
>
> Why does this work:
>
> if __name__ == 'main':
> execfile('test-data.py')
> print data
>
> and yet this doesn't (I get "NameError: global name 'data' not
> defined"):
>
> def X():
> execfile('test-data.py')
> print data
>
> where test-data.py is:
>
> data = [1,2,3,4]
>
> I checked help on execfile and could only find the following
> (mystifying) sentence:
>
> "execfile() cannot be used reliably to modify a function�s locals."
>
In the first example 'execfile' is passed globals() by default, which
'test-data.py' modifies.

In the second example 'execfile' is passed locals() by default (because
it's called from within a function), which 'test-data.py' modifies.

However, Python (well, CPython at least), optimises access to locals
within functions, which unfortunately means that changes to locals()
won't actually affect the function's locals.

Here's an example which tries to change the locals:

>>> def test():
.... x = 0
.... print "Old value of x:", x
.... locals()["x"] = 1
.... print "New value of x:", x
....
>>> test()
Old value of x: 0
New value of x: 0


Compare this with changing globals:

>>> x = 0
>>> print "Old value of x:", x
Old value of x: 0
>>> globals()["x"] = 1
>>> print "New value of x:", x
New value of x: 1
From: Inyeol Lee on
On Jun 15, 3:22 pm, Peter <peter.milli...(a)gmail.com> wrote:
> I am puzzled by what appears to be a scope issue - obviously I have
> something wrong :-)
>
> Why does this work:
>
> if __name__ == 'main':
>   execfile('test-data.py')
>   print data
>
> and yet this doesn't (I get "NameError: global name 'data' not
> defined"):
>
> def X():
>   execfile('test-data.py')
>   print data
>
> where test-data.py is:
>
> data = [1,2,3,4]
>
> I checked help on execfile and could only find the following
> (mystifying) sentence:
>
> "execfile() cannot be used reliably to modify a function’s locals."
>
> Thanks
> Peter

This is due to CPython's static optimization of local name lookup.
Dummy 'exec' statement disables this and makes your example work:

def X():
exec "None"
execfile('test-data.py')
print data

--inyeol
From: Peter on
This one seems to do the trick - thanks! :-)

On Jun 16, 10:12 am, Inyeol Lee <inyeol....(a)gmail.com> wrote:
> On Jun 15, 3:22 pm, Peter <peter.milli...(a)gmail.com> wrote:
>
>
>
>
>
> > I am puzzled by what appears to be a scope issue - obviously I have
> > something wrong :-)
>
> > Why does this work:
>
> > if __name__ == 'main':
> >   execfile('test-data.py')
> >   print data
>
> > and yet this doesn't (I get "NameError: global name 'data' not
> > defined"):
>
> > def X():
> >   execfile('test-data.py')
> >   print data
>
> > where test-data.py is:
>
> > data = [1,2,3,4]
>
> > I checked help on execfile and could only find the following
> > (mystifying) sentence:
>
> > "execfile() cannot be used reliably to modify a function’s locals."
>
> > Thanks
> > Peter
>
> This is due to CPython's static optimization of local name lookup.
> Dummy 'exec' statement disables this and makes your example work:
>
> def X():
>   exec "None"
>   execfile('test-data.py')
>   print data
>
> --inyeol

From: Peter Otten on
Inyeol Lee wrote:

> On Jun 15, 3:22 pm, Peter <peter.milli...(a)gmail.com> wrote:
>> I am puzzled by what appears to be a scope issue - obviously I have
>> something wrong :-)
>>
>> Why does this work:
>>
>> if __name__ == 'main':
>> execfile('test-data.py')
>> print data
>>
>> and yet this doesn't (I get "NameError: global name 'data' not
>> defined"):
>>
>> def X():
>> execfile('test-data.py')
>> print data
>>
>> where test-data.py is:
>>
>> data = [1,2,3,4]
>>
>> I checked help on execfile and could only find the following
>> (mystifying) sentence:
>>
>> "execfile() cannot be used reliably to modify a function's locals."
>>
>> Thanks
>> Peter
>
> This is due to CPython's static optimization of local name lookup.
> Dummy 'exec' statement disables this and makes your example work:
>
> def X():
> exec "None"
> execfile('test-data.py')
> print data
>
> --inyeol

You may also consider the following alternative:

def f():
ns = {}
execfile('test-data.py', ns)
print ns["data"]

f()

This has the advantage that it can be automatically converted to Python 3.

Peter