cPickle problem

Alex Martelli aleax at aleax.it
Mon Apr 29 17:05:41 EDT 2002


Vojin Jovanovic wrote:
        ...
>  def __getattr__(self,arg):
>   try:
>    exec 'result =' + self.e[arg]
>   except:
>    return '#U'
>   return result

Note that this __getattr__ answers "yes, here it is!" WHATEVER
attribute the object is being accessed for.

Now suppose that Python itself is accessing an instance of this
class to check if it has a certain special-method.  What happens?

Python tries accessing attribute (e.g.) '__getstate__', ready for
an AttributeError exception to mean "no such attribute", or else
to get and use (call) the result.

And the object answers "Sure, I DO have a __getstate__, and
its value is '#U'".

So of course Python tries calling '#U' when NOT ready for any
exception, since by spec, the attribute __getstate__, if it exists,
must be a callable (typically a method) with certain semantics.
But, in this case:


>>>> cPickle.dump(A,file)
> Traceback (most recent call last):
>   File "<pyshell#62>", line 1, in ?
>     cPickle.dump(A,file)
> TypeError: object of type 'string' is not callable

Indeed, object '#U', of type 'string', is NOT callable.  And yet
that is what the object CLAIMS it has as attribute __getstate__.


Any __getattr__ special method should ALWAYS raise
AttributeError when asked for any name starting and ending
with two underscores, except if it does know the name and
is specifically prepared to return some right, meaningful value
for it.  All identifiers that start and end with two underscores
are "reserved to Python" in that any Python version can add
some of them, so it's totally unsafe to *pretend* you have ones
that you don't actually know about.


Alex




More information about the Python-list mailing list