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

明明已用try-catch捕获KeyError,为何仍抛出该异常?

问题

自定义类FancyTuple访问不存在的属性a.chal时,明明在__getattr__方法中捕获了KeyError并抛出AttributeError,但异常栈仍会显示KeyError的相关信息,如何消除这个多余的异常栈条目?

代码示例

class FancyTuple:
    mapping = {1:"first", 2:"second", 3:"third", 4:"fourth", 5:"fifth"}
    reverseMapping = {"first": 1, "second": 2, "third": 3, "fourth":4 , "fifth": 5}
    
    def __init__(self, *args):
        self._values = args
        for i, arg in enumerate(args):
            setattr(self, f"{self.mapping[i+1]}", arg)
    
    def __getattr__(self, name):
        try:
            index = self.reverseMapping[name] - 1
        except KeyError:
            raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
        
        try:
            return self._values[index]
        except IndexError:
            raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
    
    def __len__(self):
        return len(self._values)

异常栈信息

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/var/folders/3t/wf6fblsn3b9byqx75s_l8g300000gn/T/ipykernel_27328/2978799403.py in __getattr__(self, name)
     11         try:
---> 12             index = self.reverseMapping[name] - 1
     13         except KeyError:

KeyError: 'chal'

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
/var/folders/3t/wf6fblsn3b9byqx75s_l8g300000gn/T/ipykernel_27328/2705563914.py in <module>
----> 1 a.chal

/var/folders/3t/wf6fblsn3b9byqx75s_l8g300000gn/T/ipykernel_27328/2978799403.py in __getattr__(self, name)
     12             index = self.reverseMapping[name] - 1
     13         except KeyError:
---> 14             raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
     15 
     16         try:

AttributeError: 'FancyTuple' object has no attribute 'chal'

解决方法

这是Python默认保留异常上下文导致的——抛出新异常时,原始触发的KeyError会被作为上下文保留并显示在栈信息里。要消除这个条目,只需在raise语句后加上from None,切断异常上下文的关联。

修改后的__getattr__方法:

def __getattr__(self, name):
    try:
        index = self.reverseMapping[name] - 1
    except KeyError:
        raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") from None
    
    try:
        return self._values[index]
    except IndexError:
        raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") from None

修改后再访问不存在的属性,异常栈只会显示最终的AttributeError,不会再出现KeyError的相关内容。

另外,也可以用dict.get()方法提前避免触发KeyError,简化代码逻辑:

def __getattr__(self, name):
    idx = self.reverseMapping.get(name)
    if idx is None:
        raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
    index = idx - 1
    try:
        return self._values[index]
    except IndexError:
        raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") from None

内容的提问来源于stack exchange,提问作者Sairam Tabibu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 18:17:39