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()
@Antimony: pickle handles namedtuple classes just fine; classes defined in a function local namespace not so much.
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.
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).
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With