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