无法重抛时捕获Python异常链中的特定异常
如何获取被外部库函数包装的原始异常
问题场景
给定以下Python代码,其中blackbox属于外部库无法修改,它会捕获say函数抛出的ValueError,并重新抛出一个通用的RuntimeError。我们需要在不修改blackbox的前提下,获取最初抛出的ValueError。
示例代码
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")
运行后的回溯信息
--------------------------------------------------------------------------- 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
解决方案
Python 3中,当在except块中抛出新异常时,原始异常会被自动保存到新异常的__context__属性中,我们可以利用这一特性获取原始异常:
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") # 捕获外部库抛出的RuntimeError,提取原始异常 try: blackbox(say, "Foo Ni Bar") except RuntimeError as wrapped_exc: # 获取原始异常 original_exception = wrapped_exc.__context__ if isinstance(original_exception, ValueError): print(f"原始异常类型: {type(original_exception).__name__}") print(f"原始异常信息: {original_exception}") # 可根据需求进一步处理原始异常
原理说明
- Python会自动维护异常的上下文关系:当在处理一个异常的过程中抛出新异常,新异常的
__context__属性会指向触发当前except块的原始异常。 - 这种隐式的上下文传递不需要外部库做任何特殊处理,是Python异常机制的默认行为。
内容的提问来源于stack exchange,提问作者Aristide
相关产品推荐
相关产品推荐

