python3使用自定义属性重新引发异常?

时间:2013-04-05 15:50:07

标签: python python-3.x

这是我需要移植的python2代码:

try:
  do_something_with_file(filename)

except:
  exc_type, exc_inst, tb = sys.exc_info()
  exc_inst.filename = filename
  raise exc_type, exc_inst, tb

使用上面的代码,通过检查异常是否具有'filename'属性,我可以通过有问题的输入文件获得整个异常。

然而python3的加注已经改变。这就是2to3给我的代码:

except Exception as e:
  et, ei, tb = sys.exc_info()
  e.filename = filename
  raise et(e).with_traceback(tb)

这给了我另一个错误,我不认为文件名属性被保留:

in __call__
    raise et(e).with_traceback(tb)
TypeError: function takes exactly 5 arguments (1 given)

我只想要透明地传递异常信息以跟踪输入文件。我想念python2的raise [exception_type[,exception_instance[,traceback]]] - 我怎么能在python3中做到这一点?

2 个答案:

答案 0 :(得分:6)

您可以设置__traceback__属性:

except Exception as e:
    et, ei, tb = sys.exc_info()
    ei.filename = filename
    ei.__traceback__ = tb
    raise ei

或直接在旧实例上调用.with_traceback()

except Exception as e:
    et, ei, tb = sys.exc_info()
    ei.filename = filename
    raise ei.with_traceback(tb)

但是,回溯已经自动附加,无需重新附加,实际上。

请参阅raise statement documentation

  

通常会在引发异常时自动创建回溯对象,并将其作为__traceback__属性附加到该属性,该属性是可写的。

在这种特定情况下,或许你想要一个不同的例外,而不是上下文?

class FilenameException(Exception):
    filename = None
    def __init__(self, filename):
        super().__init__(filename)
        self.filename = filename

try:
    something(filename)
except Exception as e:
    raise FilenameException(filename) from e

这将创建一个链式异常,如果未被捕获,则会打印两个异常,并且原始异常可用作newexception.__context__

答案 1 :(得分:4)

你不需要做任何事情;在Python 3中,重新引发的异常会自动从它们最初引发的位置获得完整的回溯。

try:
  do_something_with_file(filename)
except Exception as exc_inst:
  exc_inst.filename = filename
  raise exc_inst

这是有效的,因为PyErr_NormalizeException__traceback__语句中捕获异常时适当地设置except属性;见http://www.python.org/dev/peps/pep-3134/