Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Pickling a class with a __getattr__

11 views
Skip to first unread message

Peter Bengtsson

unread,
Apr 1, 2007, 12:38:41 PM4/1/07
to
Hi, I'm trying to pickle an object instance of a class that is like a
dict but with a __getattr__ and I'm getting pickling errors.

This works but is not good enough.

$ python2.4
>>> import cPickle as pickle
>>> class Dict(dict):
... pass
...
>>>
>>>
>>> friend = Dict(name='Zahid', age=40)
>>> friend
{'age': 40, 'name': 'Zahid'}
>>> v=pickle.dumps(friend)
>>> p=pickle.loads(v)
>>> p
{'age': 40, 'name': 'Zahid'}

This is what happens when I'm trying to be clever:

>>> import cPickle as pickle
>>> class Dict(dict):
... def __getattr__(self, key):
... return self.__getitem__(key)
...
>>> friend = Dict(name='Zahid', age=40)
>>> friend
{'age': 40, 'name': 'Zahid'}
>>> friend.name
'Zahid'
>>> v=pickle.dumps(friend)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/lib/python2.4/copy_reg.py", line 73, in _reduce_ex
getstate = self.__getstate__
File "<stdin>", line 3, in __getattr__
KeyError: '__getstate__'


Why can't I pickle the slightly more featurefull class there called
'Dict'? I've got my reasons for not going for a simple type dict but
feel that that is irrelevant right now.

Peter Otten

unread,
Apr 1, 2007, 12:48:52 PM4/1/07
to
Peter Bengtsson wrote:

> Hi, I'm trying to pickle an object instance of a class that is like a
> dict but with a __getattr__ and I'm getting pickling errors.

> This is what happens when I'm trying to be clever:


>
>>>> import cPickle as pickle
>>>> class Dict(dict):
> ... def __getattr__(self, key):
> ... return self.__getitem__(key)
> ...
>>>> friend = Dict(name='Zahid', age=40)
>>>> friend
> {'age': 40, 'name': 'Zahid'}
>>>> friend.name
> 'Zahid'
>>>> v=pickle.dumps(friend)
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> File "/usr/lib/python2.4/copy_reg.py", line 73, in _reduce_ex
> getstate = self.__getstate__
> File "<stdin>", line 3, in __getattr__
> KeyError: '__getstate__'
>
>
> Why can't I pickle the slightly more featurefull class there called
> 'Dict'?

Because you allow your __getattr__() implementation to raise the wrong kind
of exception.

>>> from cPickle import dumps, loads


>>> class Dict(dict):
... def __getattr__(self, key):

... try:
... return self[key]
... except KeyError:
... raise AttributeError
...
>>> friend = Dict(name="Zaphod", age=42)
>>> v = dumps(friend)
>>> p = loads(v)
>>> p
{'age': 42, 'name': 'Zaphod'}

Peter

Peter Bengtsson

unread,
Apr 1, 2007, 1:06:34 PM4/1/07
to

Thanks! That did the trick. I also noticed that I could define
__getstate__ and __setstate__ (needed for protocol 2) but your
solution works much better.

0 new messages