【问题标题】:How do I catch an exception in a decorator but allow the caller to catch it as well?如何在装饰器中捕获异常但允许调用者也捕获它?
【发布时间】:2011-05-14 02:11:37
【问题描述】:

我有一个可能引发异常的 python 函数。调用者捕获异常并处理它。现在我想为那个函数添加一个装饰器,捕获异常,进行一些处理,然后重新引发异常以允许原始调用者处理它。这有效,除了当原始调用者显示异常的调用堆栈时,它显示装饰器中重新引发它的行,而不是最初发生的位置。示例代码:

import sys,traceback

def mydec(func):
    def dec():
        try:
            func()
        except Exception,e:
            print 'Decorator handled exception %s' % e
            raise e
    return dec

@mydec
def myfunc():
    x = 1/0

try:
    myfunc()
except Exception,e:
    print 'Exception: %s' % e
    type,value,tb = sys.exc_info()
    traceback.print_tb(tb)

输出是:

Decorator handled exception integer division or modulo by zero
Exception: integer division or modulo by zero
  File "allbug.py", line 20, in <module>
    myfunc()
  File "allbug.py", line 9, in dec
    raise e

我希望装饰器能够处理异常,但回溯应该指示x = 1/0 行而不是raise 行。我该怎么做?

【问题讨论】:

    标签: python exception decorator


    【解决方案1】:

    只需在 catch 块中使用 raise;(即不引发任何具体的问题,只需 raise;)即可重新引发异常,而无需“重置”回溯。

    【讨论】:

    • 为了清楚起见,只需使用赤裸裸的“raise”语句。不要指定要提高什么。
    • @Graeme:没必要打你的头。这不是它自己可以想到的明显解决方案:)
    【解决方案2】:

    我刚刚编写了一个与您正在做的类似的课程,但提供了更多选项。这里是:

    class ErrorIgnore(object):
       def __init__(self, errors, errorreturn = None, errorcall = None):
          self.errors = errors
          self.errorreturn = errorreturn
          self.errorcall = errorcall
    
       def __call__(self, function):
          def returnfunction(*args, **kwargs):
             try:
                return function(*args, **kwargs)
             except Exception as E:
                if type(E) not in self.errors:
                   raise E
                if self.errorcall is not None:
                   self.errorcall(E, *args, **kwargs)
                return self.errorreturn
          return returnfunction
    

    常见用法如下:

    def errorcall(E, *args):
       print 'exception skipped', E
    
    @ErrorIgnore(errors = [ZeroDivisionError, ValueError], errorreturn = None, errorcall = errorcall)
    def myfunction(stuff):
       # do stuff
       # return stuff
       # the errors shown are skipped
    

    【讨论】:

      猜你喜欢
      • 2013-08-22
      • 2019-10-05
      • 2013-12-31
      • 2016-06-16
      • 2019-06-23
      • 2011-08-08
      • 2016-05-12
      • 2016-07-22
      • 2014-06-28
      相关资源
      最近更新 更多