__getattribute__'s error is not available in __getattr__
Ethan Furman
ethan at stoneleaf.us
Tue May 2 22:37:13 EDT 2017
On 05/02/2017 05:59 PM, Jason Maldonis wrote:
> @Steve they asked me to move it here because it was more fitting. I hope that's okay?
Yes, it's okay. ;)
> After some testing, it looks like I'm okay with how things work if the problem-object isn't a descriptor (although I do
> still things it's a bit odd that an error gets squashed, but it's no big deal).
>
> However, I use @property all the time, so that's likely why I'm running into this so often. If you can help explain to
> me what's going on in that case, that would be great! I have two examples below for the sake of discussion.
>
> Here's an example where the underlying error is completely hidden:
>
> class A(object):
> def _some_complex_code_hidden_from_the_user(self):
> # Run a bunch of complex stuff that raises an attribute error internally
> # This could go layers deep into different modules
> return self.this_doesnt_exist
>
> @property
> def x(self):
> return self._some_complex_code_hidden_from_the_user()
>
> def __getattr__(self, attr):
> raise AttributeError("raised from A.__getattr__ to stop execution")
>
> a = A()
> print(a.x)
>
>
> This results in the following output:
>
> Traceback (most recent call last):
> File "test3.py", line 17, in <module>
> print(a.x)
> File "test3.py", line 14, in __getattr__
> raise AttributeError("raised from A.__getattr__ to stop execution")
> AttributeError: raised from A.__getattr__ to stop execution
>
>
> Here the real reason the code errors (`sys.this_doesnt_exist` throwing an AttributeError) is not in the traceback's stack.
The problem is that Python cannot tell the difference between `A.x` not existing (which would raise AttributeError), and
some attribute inside `A.x` not existing (which also raises AttributeError).
There's an issue to fix this somewhere in the Python Bug Tracker (bugs.python.org) but I cannot find it at the moment
(it's quite old).
> My current opinion on this is that the error that triggered __getattr__ should be passed to __getattr__. This would
> allow us to use the "raise from" syntax.
Hmm. Since the other issue isn't making any headway this might be the best we get -- you should open a thread for it
over at Python Ideas. :)
Until then Chris' decorator is probably the easiest work around -- but you should only catch AttributeError, not everything.
--
~Ethan~
More information about the Python-list
mailing list