【问题标题】:How to detect if an exception has been raised from a try block in python?如何检测python中的try块是否引发了异常?
【发布时间】:2016-05-13 14:25:33
【问题描述】:

例如:

class ExceptionMeta(type):
  def __call__(cls, *args, **kwargs):
    if exception_raised_from_try_block:
       do_something
    else:
       do_something_else

class TimeOutError(metaclass = ExceptionMeta):
  pass

try:
  raise TimeOutError
except Exception as e:
  pass

实际问题是我有一个代码块,其中在 try - except 块中出现 TimeOut 错误。每次引发 TimeOut 错误时,我都会在 try 中捕获它 - 除了阻塞并发出重试 5 次。此 TimeOut 错误有一个对象,该对象将在引发异常的情况下收集错误跟踪,以便在调试问题时提供更多上下文。但是每次在 try 块中引发异常时,调用都会转到 call 函数,它最终会收集我不想要的错误的跟踪,因为我只是在 except 块中再次重试

在 python 中有什么方法可以使用检查或其他模块告诉我异常是从 try 块引发的吗?

【问题讨论】:

  • 你认为在 except 中会发生什么?
  • 您似乎正在尝试过滤掉可能未捕获的异常。那是对的吗?你能进一步解释你为什么要这样做吗?
  • 看起来你希望你的异常在被try 块捕获时有一个行为,如果没有被捕获到另一个行为,但它们只是一个信号 - 异常不应该有副作用。跨度>
  • 但是你为什么需要这么奇怪的功能呢?描述你正在尝试实现的功能,我觉得没有这个疯狂的概念就可以解决这个问题。
  • 欢迎来到stackoverflow。看起来这个问题受到 A/B 问题的影响:@user2819403 有问题 A,但他没有询问问题 A,而是询问他设计的解决方案 B。请编辑您的问题以显示原始问题。您尝试实现的解决方案在 Python 中并不惯用。

标签: python exception


【解决方案1】:

所以你的问题是重试一段代码......

假设你有一些类似的代码:

import random

def do_something_unreliable(msg="we have landed"):
    if random.randint(0, 10) > 1:
        raise Exception("Timed out...")
    else:
        return "Houston, {0}.".format(msg)

您可以通过以下方式重试 5 次:

for attempt in range(1, 5):
    try:
        do_something_unreliable()
    except Exception:
        # print("timeout, trying again...")
        pass
    else:
        break
else:
    do_something_unreliable()

您可以通过以下方式使其可重复使用:

def retry(fn, args=None, kwargs=None, times=5, verbose=False, exceptions=None):
    if args is None:
        args = []
    if kwargs is None:
        kwargs = {}
    if exceptions is None:
        exceptions = (Exception,)
    for attempt in range(1, times):
        try:
            return fn(*args, **kwargs)
        except exceptions as e:
            if verbose:
                print("Got exception {0}({1}), retrying...".format(
                         e.__class__.__name__, e))
    return fn(*args, **kwargs)

然后你可以写:

>>> retry(do_something_unreliable, verbose=True)
Got exception Exception(Timed out...), retrying...
Got exception Exception(Timed out...), retrying...
Got exception Exception(Timed out...), retrying...
'Houston, we have landed.'

>>> retry(do_something_unreliable, ['we are lucky'], verbose=True)
Got exception Exception(Timed out...), retrying...
Got exception Exception(Timed out...), retrying...
'Houston, we are lucky.'

你也可以看看retrying装饰器:

Retrying 是 Apache 2.0 许可的通用重试库,用 Python 编写,用于 简化将重试行为添加到几乎所有内容的任务。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 2012-05-02
    • 2017-10-04
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多