Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pickle a namedtuple instance correctly

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() 
like image 453
Dirty Penguin Avatar asked May 04 '13 17:05

Dirty Penguin


People also ask

Can you pickle a Namedtuple?

@Antimony: pickle handles namedtuple classes just fine; classes defined in a function local namespace not so much.

When can you change the value of a Namedtuple?

Since a named tuple is a tuple, and tuples are immutable, it is impossible to change the value of a field. In this case, we have to use another private method _replace() to replace values of the field. The _replace() method will return a new named tuple.

Is Namedtuple fast?

NamedTuple is the faster one while creating data objects (2.01 µs). An object is slower than DataClass but faster than NamedTuple while creating data objects (2.34 µs).


2 Answers

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.

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.

like image 148
Martijn Pieters Avatar answered Sep 30 '22 04:09

Martijn Pieters


I found this answer in another thread. This is all about the naming of the named tuple. This worked for me:

group_t =            namedtuple('group_t', 'field1, field2')  # this will work mismatched_group_t = namedtuple('group_t', 'field1, field2')  # this will throw the error 
like image 35
Ruvalcaba Avatar answered Sep 30 '22 04:09

Ruvalcaba