@property decorator doesn't raise exceptions

Rafe rafesacks at gmail.com
Sat Oct 25 23:59:29 EDT 2008


On Oct 24, 1:47 am, Rafe <rafesa... at gmail.com> wrote:
> Hi,
>
> I've encountered a problem which is making debugging less obvious than
> it should be. The @property decorator doesn't always raise exceptions.
> It seems like it is bound to the class but ignored when called. I can
> see the attribute using dir(self.__class__) on an instance, but when
> called, python enters __getattr__. If I correct the bug, the attribute
> calls work as expected and do not call __getattr__.
>
> I can't seem to make a simple repro. Can anyone offer any clues as to
> what might cause this so I can try to prove it?
>
> Cheers,
>
> - Rafe


Peter Oten pointed me in the right direction. I tried to reply to his
post 2 times and in spite of GoogleGroups reporting the post was
successful, it never showed up. Here is the repro:

The expected behavior...

>>> class A(object):
... @property
... def attribute(self):
...     raise AttributeError("Correct Error.")
>>> A().attribute
Traceback (most recent call last):
  File "<console>", line 0, in <module>
  File "<console>", line 0, in attribute
AttributeError: Correct Error.


The misleading/unexpected behavior...

>>> class A(object):
... @property
... def attribute(self):
...     raise AttributeError("Correct Error.")
... def __getattr__(self, name):
...     cls_name = self.__class__.__name__
...     msg = "%s has no attribute '%s'." % (cls_name, name)
...     raise AttributeError(msg)
>>> A().attribute
Traceback (most recent call last):
  File "<console>", line 0, in <module>
  File "<console>", line 0, in __getattr__
AttributeError: A has no attribute 'attribute'.


Removing @property works as expected...

>>> class A(object):
... def attribute(self):
...     raise AttributeError("Correct Error.")
... def __getattr__(self, name):
...     cls_name = self.__class__.__name__
...     msg = "%s has no attribute '%s'." % (cls_name, name)
...     raise AttributeError(msg)
>>> A().attribute()   # Note the '()'
Traceback (most recent call last):
  File "<console>", line 0, in <module>
  File "<console>", line 0, in attribute
AttributeError: Correct Error.


I never suspected __getattr__ was the cause and not just a symptom.
The docs seem to indicate __gettattr__ should never be called when the
attribute exisits in the class:
"Called when an attribute lookup has not found the attribute in the
usual places (i.e. it is not an instance attribute nor is it found in
the class tree for self). name is the attribute name. This method
should return the (computed) attribute value or raise an
AttributeError exception."

Is this a bug? Any idea why this happens? I can write a hack in to
__getattr__ in my class which will detect this, but I'm not sure how
to raise the expected exception.


Cheers,

- Rafe



More information about the Python-list mailing list