如何禁止显示后续异常的父异常(原因)

2024-01-18

我知道raise ... from None并已阅读当我提出自己的异常作为响应时,如何更轻松地抑制以前的异常? https://stackoverflow.com/questions/17091520/how-can-i-more-easily-suppress-previous-exceptions-when-i-raise-my-own-exception.

但是,如何在不控制从 except 子句执行的代码的情况下实现相同的效果(抑制“在处理上述异常期间,发生另一个异常”消息)?我以为sys.exc_clear()可以用于此目的,但该函数在 Python 3 中不存在。

我为什么要问这个?我有一些简单的缓存代码,看起来像(简化的):

try:
    value = cache_dict[key]
except KeyError:
    value = some_api.get_the_value_via_web_service_call(key)
    cache_dict[key] = value

当 API 调用出现异常时,输出将如下所示:

Traceback (most recent call last):
  File ..., line ..., in ...
KeyError: '...'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ..., line ..., in ...
some_api.TheInterestingException: ...

这是一种误导,因为原始的 KeyError 根本不是真正的错误。我当然可以通过将 try/ except (EAFP) 更改为键是否存在的测试 (LBYL) 来避免这种情况,但这不是很 Pythonic,也不太线程友好(并不是说上面的内容是线程安全的,而是这样)除此之外)。

期望 some_api 中的所有代码都改变它们的值是不合理的raise X to raise X from None(而且它甚至在所有情况下都没有意义)。是否有一个干净的解决方案来避免错误消息中出现不需要的异常链?

(顺便说一句,额外的问题:我在示例中使用的缓存基本上相当于cache_dict.setdefault(key, some_api.get_the_value_via_web_service_call(key)),如果 setdefault 的第二个参数可以是可调用的,并且仅在需要设置值时才会调用。没有更好/规范的方法吗?)


您在这里有几个选择。

首先,orlp 建议的更简洁的版本:

try:
    value = cache_dict[key]
except KeyError:
    try:
        value = some_api.get_the_value(key)
    except Exception as e:
        raise e from None
    cache_dict[key] = value

对于第二个选项,我假设有一个return value躲在你没有展示的地方:

try:
    return cache_dict[key]
except KeyError:
    pass
value = cache_dict[key] = some_api.get_the_value(key)
return value

第三种选择,LBYL:

if key not in cache_dict:
    cache_dict[key] = some_api.get_the_value(key)
return cache_dict[key]

对于奖励问题,定义您自己的 dict 子类,它定义__missing__:

class MyCacheDict(dict):

    def __missing__(self, key):
        value = self[key] = some_api.get_the_value(key)
        return value

希望这可以帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何禁止显示后续异常的父异常(原因) 的相关文章

随机推荐