function namespaces

D

Darren Dale

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?
 
M

Max Erickson

Darren said:
def myfunction(filename):
execfile(filename)
print testvar
What am I doing wrong?

I'm not familiar enough with execfile or the interactive interpreter to
know what you are doing wrong, but something like:

def myfunction(filename):
ns=dict()
execfile(filename, ns)
print ns['testvar']

should at least get you going. There is probably a way to pass the
namespace of the function to execfile, but I do not know it.

max
 
M

M.E.Farmer

Hello Darren,
I am not sure why you are using execfile().
Py> help(execfile)
Help on built-in function execfile:

execfile(...)
execfile(filename[, globals[, locals]])

Read and execute a Python script from a file.
The globals and locals are dictionaries, defaulting to the current
globals and locals. If only globals is given, locals defaults to
it.
Do you realize that execfile actually runs your script?

A simple import would probably be the best way to go.
#contents of myfile.py:
testvar = [1,2,3,4]

# someother.py
import myfile
print myfile.testvar

But to answer the question :
#contents of myfile.py:
testvar = [1,2,3,4]

# someother.py
# the problem is you are executing a script
# then searching in the wrong namespace.
def myfunction(filename):
execfile(filename, globals())
print testvar
hth,
M.E.Farmer
 
S

Steven Bethard

Darren said:
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
 
D

Darren Dale

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

I am writing a simulation that loads some predefined constants, depending on
the options called by the user. I originally had it set up to parse the
file, and load the constants explicitly, but then I thought that with the
existence of this handy builtin execfile, I could make write my constants
file in python, and just load it. I guess it is not the best approach.
Thanks for the advice though (everyone), I learned something.
 
S

Steve Holden

Darren said:
I am writing a simulation that loads some predefined constants, depending on
the options called by the user. I originally had it set up to parse the
file, and load the constants explicitly, but then I thought that with the
existence of this handy builtin execfile, I could make write my constants
file in python, and just load it. I guess it is not the best approach.
Thanks for the advice though (everyone), I learned something.
Aha!

Think about using the dreaded (and dangerous, but in your case
potentially extremely useful)

from config import *

regards
Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,786
Messages
2,569,626
Members
45,328
Latest member
66Teonna9

Latest Threads

Top