1

考虑以下代码:

class Test(object):
    def __enter__(self):
        pass
    def __exit__(self,type,value,trace):
        if type:
            print "Error occured: " + str(value.args)
            #if I changed the next line to 'return True', the
            #'print "should not happen"' statements are executed, but the
            #error information would be only printed once (what I want)
            return False
        return True

with Test():
    with Test():
        with Test():
            raise Exception('Foo','Bar')
        print "should not happen"
    print "should not happen"

示例输出:

发生错误:('Foo','Bar')

发生错误:('Foo','Bar')

发生错误:('Foo','Bar')

我有几个嵌套with语句,并且想要处理代码中某处引发异常的情况。我想要实现的是停止执行(上例中没有“不应该发生”的输出),但错误信息只打印一次。因此,我需要以某种方式知道是否已经处理了相同的错误。

您知道如何实现这一目标吗?

4

2 回答 2

4

你不能真正干净地做到这一点——上下文管理器要么吞下异常,要么不吞下。

如果您对从管理器传播出来的异常感到满意(如果您在此处处理任意异常,则应该如此),您可以对异常实例进行猴子修补:

def __exit__(self, type, value, trace):
    if type:
        if not getattr(value, '_printed_it_already', False):
           print "error occured: " + str(value.args)
           value._printed_it_already = True
           return False
    return True

请注意,这种猴子修补在 Python 中是不受欢迎的……我认为值得问问你实际上在做什么。通常,当一个未处理的异常打印它的堆栈跟踪时,您会非常清楚异常的args开始是什么......

于 2014-07-07T16:52:47.353 回答
1

您可以error_handled向异常添加属性并对其进行测试:

class Test(object):
    def __enter__(self):
        pass
    def __exit__(self,type,value,trace):
        if type:
            if not getattr(value,'error_handled', False):
                value.error_handled = True
                print "Error occured: " + str(value.args)

with Test():
    with Test():
        with Test():
            raise Exception('Foo','Bar')
        print "should not happen"
    print "should not happen"
于 2014-07-07T16:54:18.673 回答