New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exception chaining accepts exception classes #87168
Comments
I saw this line of code today: hyperledger-archives/sawtooth-sdk-python@c27b962#diff-eb008203eae2160c5e14c42e5fd2eee164709a93bf5136fa79cc256d4e46eaffR92 I was about to tell this guy that his code is bad since the part after the
The line doesn't fail, but it silently trims away the stacktrace of the previous exception. (Normally the stacktrace would include what's inside the I'm not sure whether this is intended behavior or not. The documentation does say "the second expression must be another exception class or instance" but (a) it's not clear what the use case is when it's a class and (b) I doubt that the person who wrote the code above, and any other person who writes such code, would be aware that their traceback got snipped until it's too late and they're stuck with a bug report with incomplete information. |
It is intended behaviour. https://www.python.org/dev/peps/pep-3134/#explicit-exception-chaining >>> raise ValueError('bad value') from IndexError('bad index')
IndexError: bad index
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: bad value If you wish to chain from the current exception, you have to chain from the current exception, and not create a new one. This is not an interpreter bug, it's working fine. Your first instinct was correct: your colleague had written "bad code" and his intention was probably to raise from the exception he had just caught. Or just don't do anything. A |
People barely know how to use the right form of this feature. Providing them with a wrong form that's confusingly similar to the right form and fails silently is an unfortunate choice. "Or just don't do anything. A With the wrong message, yes. |
How do you "the wrong message" to implicitly chain exceptions rather The difference between:
and
is that the first traceback says: "The above exception was the direct cause of the following exception" and the second says: "During handling of the above exception, another exception occurred" Both messages are correct, but if the difference beween the two matters |
Ram: I think you're conflating two separate things, here: (1) The ability to use an exception *class* instead of an exception *instance* in the "from" clause - that is, the ability to do "raise ValueError from TypeError" in place of "raise ValueError from TypeError()" (2) The lack of a traceback from the local exception-handling context when doing raise from. The two are independent: you'll see the same lack of traceback that you described if you do "raise ValueError from TypeError()" instead of "raise ValueError from TypeError". Both behaviours are by design (as Steven already pointed out for (2)). However, on point (1), there may be a documentation bug here. The reference manual, under https://docs.python.org/3/reference/simple_stmts.html#the-raise-statement, says:
However, this description appears not to match the implementation. In the case that the second expression is an exception class, it's *not* attached to the raised exception as the __cause__ attribute. Instead, the exception class is first instantiated, and then the resulting exception *instance* is attached to the raised exception as the __cause__ attribute. The corresponding part of the implementation is here: Lines 4758 to 4763 in b745a61
Demonstration: >>> try:
... raise ZeroDivisionError() from RuntimeError
... except Exception as e:
... exc = e
...
>>> exc.__cause__
RuntimeError()
>>> exc.__cause__ is RuntimeError # reference manual would suggest this is True
False
>>> isinstance(exc.__cause__, RuntimeError) # actual behaviour
True |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: