[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

in a pickle

On 07/03/2019 00:18, Ethan Furman wrote:
> On 03/06/2019 10:30 AM, duncan smith wrote:
>> ?I've been trying to figure out why one of my classes can be
>> pickled but not unpickled. (I realise the problem is probably with the
>> pickling, but I get the error when I attempt to unpickle.)
>> A relatively minimal example is pasted below.
>> --> import pickle
>> --> class test(dict):
>> ...??? def __init__(self, keys, shape=None):
>> ...??????? self.shape = shape
>> ...??????? for key in keys:
>> ...??????????? self[key] = None
>> ...??? def __setitem__(self, key, val):
>> ...??????? print (self.shape)
>> ...??????? dict.__setitem__(self, key, val)
>> ...
>> --> x = test([1,2,3])
>> None
>> None
>> None
>> --> s = pickle.dumps(x)
>> --> y = pickle.loads(s)
>> Traceback (most recent call last):
>> ?? File "<pyshell#114>", line 1, in <module>
>> ???? y = pickle.loads(s)
>> ?? File "<pyshell#111>", line 8, in __setitem__
>> ???? print (self.shape)
>> AttributeError: 'test' object has no attribute 'shape'
> It seems to me the problem only exists because you are trying to print
> `self.shape` -- stop printing it, and everything works normally.
> What problem are you actually trying to solve?
> -- 
> ~Ethan~

Accessing self.shape at that point in the code. In my actual code I am
updating a secondary data structure and doing some sanity checking at
that point. That fails because self.shape doesn't exist. Peter's post
makes it clear that although it fails in my __setitem__() it is not via
calling my __init__(). It must be being called by pickle.loads(). So on
the basis that pickle.loads() will restore the secondary data structure
correctly, and having no need for sanity checking assuming the original
object was valid, then the problem almost goes away. e.g. I can catch
the AttributeError and just call dict.__setitem__(self, key, val). That
I still need to test. I might yet employ Peter's solution (for when I
thought I needed access to self.shape and other attributes, which I now
doubt) which is to define __new__() so that the relevant attributes do
exist when they are required.