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~ -- https://mail.python.org/mailman/listinfo/python-list