这是我需要移植的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中做到这一点?
答案 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/。