__getattribute__'s error is not available in __getattr__

Ethan Furman ethan at stoneleaf.us
Tue May 2 20:11:07 EDT 2017


On 05/02/2017 11:16 AM, Jason Maldonis wrote:

> Here is the simplest example showing what I mean (there are many more
> complicating variations this, and unfortunately I'm running into some of
> them):
>
> class A(object):
>      def __getattr__(self, attr):
>          raise AttributeError("raised from A.__getattr__ to stop execution")
>
> a = A()
> print(a.x)
>
> results in:
>
> Traceback (most recent call last):
>    File "test.py", line 6, in <module>
>      print(a.x)
>    File "test.py", line 3, in __getattr__
>      raise AttributeError("raised from A.__getattr__ to stop execution")
> AttributeError: raised from A.__getattr__ to stop execution
>
> The thing to note here is that the AttributeError on the normal
> __getattribute__'s lookup isn't in the stack trace.  That error is:
> Traceback (most recent call last):
>    File "test2.py", line 35, in <module>
>      print(a.x)
> AttributeError: 'A' object has no attribute 'x'
>
> -- that last line, "AttributeError: 'A' object has no attribute 'x'" does
> not appear in the stack trace for my above example (because __getattr__ is
> implemented).  This is because in python's attribute lookup order,
> __getattr__ is called if an AttributeError is raised, and that raised
> AttributeError gets completely discarded.
>
> So basically I want access to the intermediate AttributeError that caused
> __getattr__ to be raised in the first place.

Why?  In most cases* you know which object is missing -- it's the `attr` parameter above.

*The exception being an AttributeError raised inside a descriptor.

--
~Ethan~



More information about the Python-list mailing list