function namespaces

Steven Bethard steven.bethard at gmail.com
Tue Mar 8 19:38:00 EST 2005


Darren Dale wrote:
> Hi,
> 
> I have a variable saved in a file like this
> 
> #contents of myfile.py:
> testvar = [1,2,3,4]
> 
> and I am trying to write a function that does something like this:
> 
> def myfunction(filename):
>         execfile(filename)
>         print testvar
> 
> The problem I am running into is that the global name testvar is not
> defined, but I dont understand why. I tried calling dir() in the function,
> which does list testvar. I tried declaring tesvar a global before calling
> execfile, and that didnt help. If I just run execfile('myfile.py') in the
> interactive interpretter, testvar is loaded and I can continue my work.
> 
> What am I doing wrong? 

I believe the problem is that, when myfunction is compiled, testvar is 
determined to be a global variable (since it's not assigned to in the 
function body).  Thus, even though execfile properly adds testvar as a 
local, the code object for myfunction is trying to look testvar up as a 
global.  You can check this using dis.dis:

py> dis.dis(myfunction)
   2           0 LOAD_GLOBAL              0 (execfile)
               3 LOAD_FAST                0 (filename)
               6 CALL_FUNCTION            1
               9 POP_TOP

   3          10 LOAD_GLOBAL              2 (testvar)
              13 PRINT_ITEM
              14 PRINT_NEWLINE
              15 LOAD_CONST               0 (None)
              18 RETURN_VALUE

So yes, Python is trying to load testvar as a global.

If testvar should be a global, do something like:

py> def myfunction(filename):
...     execfile(filename, globals())
...     print testvar
...
py> myfunction('myfile.py')
[1, 2, 3, 4]
py> testvar
[1, 2, 3, 4]

and your code should run fine.

If testvar should be a local, you'll have troubles using execfile.  Read 
the execfile docs[1] which have the warning:

"Warning: The default locals act as described for function locals() 
below: modifications to the default locals  dictionary should not be 
attempted. Pass an explicit locals  dictionary if you need to see 
effects of the code on locals after function execfile() returns. 
execfile() cannot be used reliably to modify a function's locals."

The fact that testvar shows up in the locals() is just part of that 
"cannot be used reliably" part.  Don't rely on this -- AFAICT, it's a 
implementation detail, not something guaranteed by the language.

It does seem to work for me with the exec statement though:

py> def myfunction(filename):
...     exec file(filename).read()
...     print testvar
...
py> myfunction('myfile.py')
[1, 2, 3, 4]
py> testvar
Traceback (most recent call last):
   File "<interactive input>", line 1, in ?
NameError: name 'testvar' is not defined

So you might approach it this way.


Generally, I avoid execfile within a function.  What's your use case? 
There may be a better way to approach this problem...

STeVe

[1] http://docs.python.org/lib/built-in-funcs.html#l2h-24



More information about the Python-list mailing list