You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法重抛时捕获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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 18:43:13