This code:
def abc():
raise ValueError()
def xyz():
try:
raise TypeError()
except TypeError:
abc()
xyz()
creates the following traceback:
Traceback (most recent call last):
File "<stdin>", line 8, in xyz
TypeError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 12, in <module>
File "<stdin>", line 10, in xyz
File "<stdin>", line 4, in abc
ValueError
The issue is that xyz() realizes that whatever it tries first may not succeed (in this case, it just raises TypeError), and it calls abc() as a backup plan. The fact we raised an exception in the body of xyz() is of no consequence, and if it shows up in a chain of exceptions, it’s just misleading noise.
That we got an exception in abc(), however, is a real error, and I want to see it. I would like to find a way to print abc’s exception without seeing xyz’s exception. The problem is that only xyz knows this is the case.
abc() could easily suppress the incoming chain of exceptions with raise ValueError() from None
, but abc() doesn’t know about xyz, so it doesn’t know that it’s caller is handling an inconsequential exception, so it doesn’t know whether ‘from None’ is a good idea (for all it knows, it’s caller could have hit a real error).
Similarly, the caller of xyz() could decide just to print the last exception without the rest of a chain, but the caller of xyz() doesn’t necessarily know what xyz() is doing internally.
I think the only good place to handle this in inside xyz() itself, but I don’t see a way of doing that short of not calling abc() from an except block. That’s certainly possible, but the code gets crufty, particularly in larger examples.
Is there a way that xyz can call abc from its except block but not have its own exception “in the chain”?