如何防止多次捕获异常

时间:2016-07-12 13:32:57

标签: python oop exception exception-handling

有没有办法防止在将堆栈升级到程序的最高级别时多次捕获异常?

这是一个非常简化的代码示例,用于说明这种现象:

def try_except_block(smthg):
   try:
     smthg.run()
   except Exception as e:
     print("WRONG")
     raise e

def re_call():
   f2 = Foo(True) # will throw an exception
   try_except_block(f2)

class Foo:
  def __init__(self, t):
    self.throw = t
  def run(self):
    if self.throw:
      raise KeyError
    else:
      re_call()

if __name__ == '__main__':
  f = Foo(False) # won't throw an exception
  try_except_block(f)

输出:

WRONG
WRONG
Traceback (most recent call last):
  File "exception_loosing_args.py", line 26, in <module>
    try_except_block(f)
  File "exception_loosing_args.py", line 9, in try_except_block
    raise e
  File "exception_loosing_args.py", line 6, in try_except_block
    smthg.run()
  File "exception_loosing_args.py", line 22, in run
    re_call()
  File "exception_loosing_args.py", line 13, in re_call
    try_except_block(f2)
  File "exception_loosing_args.py", line 9, in try_except_block
    raise e
  File "exception_loosing_args.py", line 6, in try_except_block
    smthg.run()
  File "exception_loosing_args.py", line 20, in run
    raise KeyError
KeyError

我只打印一次&#34;错误&#34;。

在我的软件中,try_except_block函数被包装到一个对象中,我有想法设置这个对象的属性,该属性可以将异常语句标记为&#34;已经访问过&#34;或不。我不喜欢这个想法,因为这可能导致这种可能的副作用。还有另外一个吗?

示例我想到的(class属性由全局变量flag模拟):

flag = False

def try_except_block(smthg):
   global flag
   try:
     smthg.run()
   except Exception as e:
     if not flag:
       print("WRONG")
       flag = True
     raise e

def re_call():
   f2 = Foo(True) # will throw an exception
   try_except_block(f2)

class Foo:
  def __init__(self, t):
    self.throw = t
  def run(self):
    if self.throw:
      raise KeyError
    else:
      re_call()

if __name__ == '__main__':
  f = Foo(False) # won't throw an exception
  try_except_block(f)

输出:

WRONG
Traceback (most recent call last):
  File "exception_loosing_args.py", line 28, in <module>
    try_except_block(f)
  File "exception_loosing_args.py", line 11, in try_except_block
    raise e
  File "exception_loosing_args.py", line 6, in try_except_block
    smthg.run()
  File "exception_loosing_args.py", line 24, in run
    re_call()
  File "exception_loosing_args.py", line 15, in re_call
    try_except_block(f2)
  File "exception_loosing_args.py", line 11, in try_except_block
    raise e
  File "exception_loosing_args.py", line 6, in try_except_block
    smthg.run()
  File "exception_loosing_args.py", line 22, in run
    raise KeyError
KeyError

1 个答案:

答案 0 :(得分:2)

我不完全理解为什么你的代码会做它的功能,但是可能适合的事情是将异常对象标记为已经看到,而不是设置全局标志。像这样:

def try_except_block(smthg):
    try:
        smthg.run()
    except Exception as e:
        if not hasattr(e, "teb_already_seen"):
            setattr(e, "teb_already_seen", True)
            print("WRONG")
        raise e

这样,try_except_block完成的额外处理只会发生一次每个异常对象,这可能是你想要的。