在Python中是否有使用异常链的标准方法?就像Java引起的'异常'?
这是一些背景知识。
我有一个包含一个主要异常类DSError
的模块:
class DSError(Exception):
pass
这个模块中的某个地方会有:
try:
v = my_dict[k]
something(v)
except KeyError as e:
raise DSError("no key %s found for %s" % (k, self))
except ValueError as e:
raise DSError("Bad Value %s found for %s" % (v, self))
except DSError as e:
raise DSError("%s raised in %s" % (e, self))
基本上这段代码应该只抛出DSError并告诉我发生了什么以及为什么。问题是try块可能会抛出很多其他异常,所以我更喜欢我能做的事情:
try:
v = my_dict[k]
something(v)
except Exception as e:
raise DSError(self, v, e) # Exception chained...
这是标准的pythonic方式吗?我没有在其他模块中看到异常链,那么如何在Python中完成呢?
答案 0 :(得分:101)
Exception chaining仅适用于Python 3,您可以在其中编写:
try:
v = {}['a']
except KeyError as e:
raise ValueError('failed') from e
产生类似
的输出Traceback (most recent call last):
File "t.py", line 2, in <module>
v = {}['a']
KeyError: 'a'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "t.py", line 4, in <module>
raise ValueError('failed') from e
ValueError: failed
在大多数情况下,您甚至不需要from
; Python 3默认显示异常处理期间发生的所有异常,如下所示:
Traceback (most recent call last):
File "t.py", line 2, in <module>
v = {}['a']
KeyError: 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "t.py", line 4, in <module>
raise ValueError('failed')
ValueError: failed
您可以在 Python 2 中添加自定义属性,例如:
class MyError(Exception):
def __init__(self, message, cause):
super(MyError, self).__init__(message + u', caused by ' + repr(cause))
self.cause = cause
try:
v = {}['a']
except KeyError as e:
raise MyError('failed', e)
答案 1 :(得分:5)
这是你要求的吗?
class MyError(Exception):
def __init__(self, other):
super(MyError, self).__init__(other.message)
>>> try:
... 1/0
... except Exception, e:
... raise MyError(e)
Traceback (most recent call last):
File "<pyshell#27>", line 4, in <module>
raise MyError(e)
MyError: division by zero
如果要存储原始异常对象,您当然可以在自己的异常类__init__
中执行此操作。您实际上可能希望存储回溯,因为异常对象本身不提供有关异常发生位置的有用信息:
class MyError(Exception):
def __init__(self, other):
self.traceback = sys.exc_info()
super(MyError, self).__init__(other.message)
在此之后,您可以访问异常的traceback
属性以获取有关原始异常的信息。 (Python 3已将此作为异常对象的__traceback__
属性提供。)