views:

477

answers:

2

I am trying to write a small function that gets a variable name, check if it exists, and if not loads it from a file (using pickle) to the global namespace.

I tried using this in a file:

import cPickle

#
# Load if neccesary
#
def loadfile(variable, filename):
    if variable not in globals():
        cmd = "%s = cPickle.load(file('%s','r'))" % (variable, filename)
        print cmd
        exec(cmd) in globals()

But it doesn't work - the variable don't get defined. What am I doing wrong?

+2  A: 

You could alway avoid exec entirely:


import cPickle

#
# Load if neccesary
#
def loadfile(variable, filename):
    g=globals()
    if variable not in g:
        g[variable]=cPickle.load(file(filename,'r'))


EDIT: of course that only loads the globals into the current module's globals.

If you want to load the stuff into the globals of another module you'd be best to pass in them in as a parameter:


import cPickle

#
# Load if neccesary
#
def loadfile(variable, filename, g=None):
    if g is None:
        g=globals()
    if variable not in g:
        g[variable]=cPickle.load(file(filename,'r'))

# then in another module do this
loadfile('myvar','myfilename',globals())

John Montgomery
This works only when I load my file with execfile, but not when I load it with import. Why is that? Thanks!
R S
Probably because the global variables are only global to the module they are in.
John Montgomery
Thanks.Is there a way to get from a module to the globals() of the interpreter automatically?
R S
There is no globals() for the interpreter. The closest thing is the __builtins__
John Montgomery
+2  A: 

Using 'globals' has the problem that it only works for the current module. Rather than passing 'globals' around, a better way is to use the 'setattr' builtin directly on a namespace. This means you can then reuse the function on instances as well as modules.

import cPickle

#
# Load if neccesary
#
def loadfile(variable, filename, namespace=None):
    if module is None:
        import __main__ as namespace
    setattr(namespace, variable, cPickle.load(file(filename,'r')))

# From the main script just do:
loadfile('myvar','myfilename')

# To set the variable in module 'mymodule':
import mymodule
...
loadfile('myvar', 'myfilename', mymodule)

Be careful about the module name: the main script is always a module main. If you are running script.py and do 'import script' you'll get a separate copy of your code which is usually not what you want.

Duncan