Consider the following Python code:
def say(words):
for word in words:
if word == "Ni":
raise ValueError("We are no longer the knights who say Ni!")
print(word)
def blackbox(function, sentence):
words = sentence.split()
try:
function(words)
except Exception as e:
raise RuntimeError("Generic Error")
blackbox(say, "Foo Ni Bar")
It prints the following traceback:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [35], in blackbox(function, sentence)
9 try:
---> 10 function(words)
11 except Exception as e:
Input In [35], in say(words)
3 if word == "Ni":
----> 4 raise ValueError("We are no longer the knights who say Ni!")
5 print(word)
ValueError: We are no longer the knights who say Ni!
During handling of the above exception, another exception occurred:
RuntimeError Traceback (most recent call last)
Input In [35], in <cell line: 14>()
11 except Exception as e:
12 raise RuntimeError("Generic Error")
---> 14 blackbox(say, "Foo Ni Bar")
Input In [35], in blackbox(function, sentence)
10 function(words)
11 except Exception as e:
---> 12 raise RuntimeError("Generic Error")
RuntimeError: Generic Error
Assume I am only interested in the first error. I could simply reraise it by replacing raise RuntimeError("Generic Error")
by raise e
in blackbox()
: end of the story.
Except (!) that I cannot modify the code of blackbox()
, which belongs to an external library.
How can I obtain the same result without touching it? My guess is that I could wrap the call to blackbox()
in a try... except...
, retrieve the chain of exceptions, and select the one I am interested in. But I failed to find anywhere how to do such a thing.
Edit: changed the name and the signature of the second function to make the constraints clearer.
Answering my own question. It is enough to catch the final exception and raise
its context, i.e., replace the last line by:
try:
blackbox(say, "Foo Ni Bar")
except Exception as e:
raise e.__context__
Traceback:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Input In [105], in <cell line: 14>()
14 try:
---> 15 blackbox(say, "Foo Ni Bar")
16 except Exception as e:
Input In [105], in blackbox(function, sentence)
11 except Exception as e:
---> 12 raise RuntimeError("Generic Error")
RuntimeError: Generic Error
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
Input In [105], in <cell line: 14>()
15 blackbox(say, "Foo Ni Bar")
16 except Exception as e:
---> 17 raise e.__context__
Input In [105], in blackbox(function, sentence)
8 words = sentence.split()
9 try:
---> 10 function(words)
11 except Exception as e:
12 raise RuntimeError("Generic Error")
Input In [105], in say(words)
2 for word in words:
3 if word == "Ni":
----> 4 raise ValueError("We are no longer the knights who say Ni!")
5 print(word)
ValueError: We are no longer the knights who say Ni!