How to pickle a namedtuple instance correctly

namedtuple, pickle, python, python-2.7

Solution

Create the named tuple outside of the function:

from collections import namedtuple
import pickle

P = namedtuple("P", "one two three four")

def pickle_test():
    my_list = []
    abe = P("abraham", "lincoln", "vampire", "hunter")
    my_list.append(abe)
    with open('abe.pickle', 'wb') as f:
        pickle.dump(abe, f)

pickle_test()

Now `pickle` can find it; it is a module global now. When unpickling, all the `pickle` module has to do is locate `__main__.P` again. In your version, `P` is a local, to the `pickle_test()` function, and that is not introspectable or importable.

Note that `pickle` stores just the module and the class name, as taken from the class's `__name__` attribute. Make sure that the first argument of the `namedtuple()` call matches the global variable you are assigning to; `P.__name__` must be `"P"`!

It is important to remember that `namedtuple()` is a class factory; you give it parameters and it returns a class object for you to create instances from. `pickle` only stores the data contained in the instances, plus a string reference to the original class to reconstruct the instances again.

Problem

I'm learning how to use pickle. I've created a namedtuple object, appended it to a list, and tried to pickle that list. However, I get the following error: ``` pickle.PicklingError: Can't pickle <class '__main__.P'>: it's not found as __main__.P ``` I found that if I ran the code without wrapping it inside a function, it works perfectly. Is there an extra step required to pickle an object when wrapped inside a function? Here is my code: ``` from collections import namedtuple import pickle def pickle_test(): P = namedtuple("P", "one two three four") my_list = [] abe = P("abraham", "lincoln", "vampire", "hunter") my_list.append(abe) with open('abe.pickle', 'wb') as f: pickle.dump(abe, f) pickle_test() ```

Original source

Related problems