I have a list of objects of various types that I want to pickle. I would like to pickle only those which are pickleable. Is there a standard way to check if an object is of
There's the dill.pickles method in dill package that does just that.
>>> class Foo(object):
... x = iter([1,2,3])
...
>>> f = Foo()
>>>
>>> dill.pickles(f)
False
We can use methods in dill to look for what causes the failure.
>>> dill.detect.badtypes(f)
>>> dill.detect.badtypes(f, depth=1)
{'__setattr__': , '__reduce_ex__': , '__reduce__': , '__str__': , '__format__': , '__getattribute__': , '__class__': , '__delattr__': , '__subclasshook__': , '__repr__': , '__hash__': , 'x': , '__sizeof__': , '__init__': }
>>> dill.detect.badtypes(f, depth=1).keys()
['__setattr__', '__reduce_ex__', '__reduce__', '__str__', '__format__', '__getattribute__', '__class__', '__delattr__', '__subclasshook__', '__repr__', '__hash__', 'x', '__sizeof__', '__init__']
So, the only thing that's failing that's not a "built-in" method of the class is x… so that's a good place to start. Let's check 'x', then replace it with something else if it's the problem.
>>> dill.pickles(Foo.x)
False
>>> Foo.x = xrange(1,4)
>>> dill.pickles(Foo.x)
True
Yep, x was causing a failure, and replacing it with an xrange works because dill can pickle an xrange. What's left to do?
>>> dill.detect.badtypes(f, depth=1).keys()
[]
>>> dill.detect.badtypes(f, depth=1)
{}
>>> dill.pickles(f)
True
>>>
Apparently (likely because references to x in the class __dict__ now pickle), f now pickles… so we are done.
dill also provides trace to show the exact path in pickling the object.
>>> dill.detect.trace(True)
>>> dill.pickles(f)
T2:
F2:
T1:
F2:
T1:
D2:
Si: xrange(1, 4)
F2:
D2:
True