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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to