Unpickle error -- "object has no attribute ...."

Peter Otten __peter__ at web.de
Mon Aug 29 05:02:27 EDT 2011


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"""



More information about the Python-list mailing list