Python – Saving variables in functions – python

Saving variables in functions – python… here is a solution to the problem.

Saving variables in functions – python

I

want to save all the variables I created in a particular function to disk at once to load them later. Some type of thing:

>>> def test():
      a=1
      b=2
      save.to.file(filename='file', all.variables)

>>> load.file('file')
>>> a
>>> 1

Is there a way to do this in Python? I know cPickle can do this, but as far as I know, cPickle.dump() has to be typed for each variable, and my script has dozens. Also, cPickle seems to store only values and not variable names, so it’s important to remember the order in which the data was originally saved.

Solution

Assuming all the variables you want to save are local to the current function, you can >locals by Get their features. It’s almost always a very bad idea, but it’s doable.

For example:

def test():
    a=1
    b=2
    pickle.dump(file, locals())

If you print locals(), you’ll see that it’s just a dictionary with a key for each local variable. So when you load pickle later, you will get the same instructions. If you want to inject it into your local environment, you can… But you have to be very careful. For example, this function:

def test2():
    locals().update(pickle.load(file))
    print a

… will be compiled to expect A to be global, not local, so the fact that you updated local A will be invalid.

This is just one of the reasons why doing so is not a good idea.

So, what is the right thing to do?

At its simplest, there is no whole bunch of variables, just a dictionary with a large number of keys. Then you can pickle and unpickle dictionaries, everything is trivial.

Alternatively, optionally, use tuples to explicitly pickle and unpickle the variables you want:

def test():
    a = 1
    b = 2
    pickle.dump(file, (a, b))

def test2():
    a, b = pickle.load(file)
    print a

In the comments, you say you want pickle a slew or variable, skipping anything that can’t be pickle.

To make things simpler, suppose you actually just want to pickle a dictionary, skipping any values that can’t pickle. (The above should explain why this solution is still completely generic.) )

So, how do you know if a value can be pickle? Trying to predict this is a tricky problem. Even if you have a perfect list of all the marinatable types, this still won’t help — you can marinate a list full of integers, but not a list full of bind instance methods.

This kind of thing is why < a href="http://docs.python.org/3/glossary.html#term-eafp" rel="noreferrer noopener nofollow" >EAFP (“it’s easier to ask forgiveness than permission”) is an important principle in duck type languages such as Python. * The way to determine if something can be pickle is to pickle it and see if an exception occurs.

Here’s a simple demo:

def is_picklable(value):
    try:
        pickle.dumps(value)
    except TypeError:
        return False
    else:
        return True

def filter_dict_for_pickling(d):
    return {key: value for key, value in d.items() if is_picklable((key, value))}

If you put the entire stored procedure in a wrapper function, you can make it more concise and efficient:

def pickle_filtered_dict(d, file):
    for key, value in d.items():
        pickle.dump((key, value), file)
    except TypeError:
        pass

def pickles(file):
    try:
        while True:
            yield pickle.load(file)
    except EOFError:
        pass

def unpickle_filtered_dict(file):
    return {key: value for key, value in pickles(file)}

Related Problems and Solutions