It seems Python handles AttributeError exception non-standard.
When a class defines __getattr__ method, it swallows this exception instead of propagation further to top of the stack. Is the original exception lost ?
class A(object):
@property
def test(self):
raise AttributeError('message which should not be lost')
return 'this would never return'
def __getattr__(self, name):
print 'Trying get attribute: ', name
# how decide if AttributeError was already raised ??
return 42
a = A()
print a.test
# Trying get attribute: test
# 42
Imagine the AttributeError exception may arise anywhere at arbitrary depth in call chain.
The question is how preserve the original exception instance with 'message which should not be lost' message ? Is there some way how keep the AttributeError without recourse to workarounds like replacing with different exception class ?
You are giving the object.__getattribute__() handler a signal that the attribute doesn't exist by raising an AttributeError. The defined behaviour is to then call __getattr__ instead. The exception is lost, it was handled by __getattribute__. From the documentation:
Called unconditionally to implement attribute accesses for instances of the class. If the class also defines
__getattr__(), the latter will not be called unless__getattribute__()either calls it explicitly or raises anAttributeError.
If you don't want __getattribute__ to handle the exception, you need to move your __getattr__ behaviour over to a custom __getattribute__ method instead:
class A(object):
@property
def test(self):
raise AttributeError('message which should not be lost')
return 'this would never return'
def __getattribute__(self, name):
try:
value = super(A, self).__getattribute__(name)
except AttributeError as ae:
# chance to handle the attribute differently
# if not, re-raise the exception
raise ae
Note that the hasattr() function behaves the same way; it'll return False when an exception is raised when trying to access the attribute.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With