7

这是我需要移植的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

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

但是 python3 的 raise 已经改变。这就是 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中做到这一点?

4

2 回答 2

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)

但是,traceback 已经自动附加了,真的不需要重新附加它。

请参阅raise声明文档

回溯对象通常在引发异常时自动创建并作为__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__.

于 2013-04-05T15:55:05.570 回答
6

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

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

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

于 2013-04-05T16:01:14.167 回答