__getattr__ and pickle

Christian Tismer tismer at appliedbiometrics.com
Thu Jul 6 12:14:28 EDT 2000


Hmm, have to correct myself a little...

Christian Tismer wrote:
> 
> Hi Sean,
...
> > The __getattr__ hook achieves a Delphi-like effect
> > in which attributes of these sub-ordinate objects
> > appear as attributes of the top level object.
> >
> > It seemed like a good idea at the time:-)
> 
> Well, I see that your __getattr__ is a little insane.
> 
>         def __getattr__(self,n):
>                 if hasattr(self.CurPos,n):
>                         return getattr(self.CurPos,n)
>                 else:
>                         raise PyxieException (
>                         "No attribute '%s' on xTree or current xNode" % n)
> 
> It redirects *every* reading attribute access to the CurPos
> object, so Pickle can't even figure out what your xTree's
> class is. Also, the CurPos object can's be saved with it,
> nothing is accessible.

I was not correct here. According to
http://www.python.org/doc/ref/attribute-access.html
section 3.3.2, the attribute lookup first walks the usual
way, before __getattr__ is invoked.

The problem with your solution is simply this:
(p|cP)ickle does not recreate your curpos object
which you create in __init__ . __init__ is not
called at all.

Now the following happens:
When *ickle tries to reconstruct your object, it is
looking for a __setstate__ property which is not there.
So, __getattr__ is called which then tries to find
self.curpos, which is also not there, causing
__getattr__ to be called, which in turn...... *POFF*.

The easy solution is this:
Give it a __setstate__ method that just creates
the curpos object, like __init__would do.

cheers - chris

file picklish.py:
-------------------------
class magic:
    def __init__(self):
        self.uh = "oh"

class ughh:
    def __getattr__(self, n):
        print "getattr called on", n
        if hasattr(self.curpos, n):
            return getattr(self.curpos, n)
        raise AttributeError, n
    def __init__(self):
        self.curpos = magic()

    def __setstate__(self, state):
        self.curpos = magic()

import pickle, cPickle

def test(use_cPickle = 0):
    pick= (pickle, cPickle) [use_cPickle]
    a = ughh()
    b = pick.dumps(a)
    c = pick.loads(b)
    return c


-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaunstr. 26                  :    *Starship* http://starship.python.net
14163 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     where do you want to jump today?   http://www.stackless.com




More information about the Python-list mailing list