luvspython wrote: > I have an application that needs to keep a history of the values of > several attributes of each of many instances of many classes. The > history-keeping logic is in a helper class, HistoryKeeper, that's > inherited by classes like Vehicle in the example below. > > Pickling an instance of Vehicle works, but unpickling fails with: > "Vehicle object has no attribute > '_orderedArgNames'" (_orderedArgNames is an attribute in > HistoryKeeper that tells the attributes for which history must be > kept.) > > During unpickling, the exception occurs at the 2nd line in the > __getattribute__ method: > if item not in object.__getattribute__(self, > '_orderedArgNames'): > > FWIW, cPickle fails the same way. > > Below is a stripped-down example that fails in unpickling. > > Can anyone explain why it fails and what I can do to fix it?
By default unpickling an object does *not* invoke its __init__() method; instead it creates an instance and then updates the __dict__ attribute of that instance. You intercept attribute access with __getattribute__, so to get hold of __dict__ you need to know __dict__["_orderedArgNames"] first, i. e. you run into a bootstrap problem. To fix the error I'd try special-casing "__dict__" def __getattribute__(self, item, ...): if item == "__dict__": return super(HistoryKeeper, self).__getattribute__(item) ... or making _orderedArgNames a class attribute: class HistoryKeeper(object): def __init__(self, orderedArgs): for arg, value in orderedArgs.items(): if arg != 'self': self.Set(arg, value) ... class Vehicle(HistoryKeeper): _orderedArgNames = "tag", "make", "model" ... If that doesn't work out you can write your own __reduce_ex__() method to customise pickling, see http://docs.python.org/library/pickle.html#object.__reduce_ex__ By the way, docstrings belong below the def not above: def f(): """Explain f() here""" -- http://mail.python.org/mailman/listinfo/python-list