如何为多个功能设置标准异常处理程序

时间:2018-07-18 05:30:59

标签: python

比方说,我有三个函数可做不同的事情,但应以相同的方式对一组异常做出反应。其中之一可能看起来像:

def get_order_stat(self, Order_id):
    status_returned = False
    error_count = 0
    while status_returned == False:
        try:
            stat_get = client.queryOrder(orderId=Order_id)
        except MalformedRequest:
            print('Order ID not yet findable, keep trying')
            error_count += 1
            time.sleep(int(1))
        except InternalError:
            print('Order check returned InternalError, keep trying')
            error_count += 1
            time.sleep(int(1))
        except StatusUnknown:
            print('Order check returned StatusUnknown, keep trying')
            error_count += 1
            time.sleep(int(1))
        else:
            status = stat_get['status']
            status_returned = True
        finally:
            if error_count >= 10:
                print('Error loop, give up')
                break
    return status

绝大多数代码是异常处理,我想避免在每个需要它的函数中重复它。有没有一种方法可以定义类似包含处理代码的异常处理函数?理想情况下,我的功能可以有效地结束:

def get_order_stat(self, Order_id):
    status_returned = False
    while status_returned == False:
        try:
            stat_get = client.queryOrder(orderId=Order_id)
        except:
            handler_function()
        else:
            status = stat_get['status']
            status_returned = True
    return status

2 个答案:

答案 0 :(得分:1)

您实际上已经做到了。只需在某个地方定义handler_function(),并在try块中引发Exception时调用它。

也许有用:您可以将Exception绑定到变量,并在处理程序函数中将其用于异常处理:

except Exception as e:
    handler_function(e)

然后,您可以例如执行`print(e)̀以发出异常,或对函数中的不同异常进行不同的处理。希望有帮助!

如果您不想变得笼统,也可以在一行中指定几个例外,但是用一条语句捕获所有特定例外:

 except (ExceptionType1, ExceptionType2, ExceptionType3) as e:
     handler_function(e)

答案 1 :(得分:1)

我可能会编写一个装饰器函数来处理异常;例如使用functool.wraps

from functool import wraps
def retry(f):
  @wraps(f)
  def wrapper(*args, **kwargs):
    error_count = 0
    while error_count < 10:
      try:
        return f(*args, **kwargs)
      except MalformedRequest:
        print('Order ID not yet findable, keep trying')
      except InternalError:
        print('Order check returned InternalError, keep trying')
      error_count += 1
      time.sleep(int(1))
    print('Error loop, give up')
    return None
  return wrapper

然后,您可以编写一个非常简单的API调用函数,并使用重试包装器将其包装:

@retry
def get_order(order_id):
  stat_get = client.queryOrder(orderId=order_id)
  return stat_get['status']

在原始功能中,请注意,您可以将try ... else块的内容移动到主try块中,而不会影响逻辑(从查询结果不会引发与网络相关的异常之一),然后您可以返回try块,而不必安排停止循环。然后,我在这里将try块的内容分解为get_order()。我对剩余的循环进行了一些重组,然后将其转换为装饰器形式。