Python异常链
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16414744/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python exception chaining
提问by Ayman
Is there a standard way of using exception chains in Python? Like the Java exception 'caused by'?
是否有在 Python 中使用异常链的标准方法?像“由”引起的 Java 异常?
Here is some background.
这是一些背景。
I have a module with one main exception class DSError:
我有一个包含一个主要异常类的模块DSError:
class DSError(Exception):
pass
Somewhere within this module there will be:
在这个模块中的某个地方将有:
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))
Basically this snippet should throw only DSError and tell me what happened and why. The thing is that the try block might throw lots of other exceptions, so I'd prefer if I can do something like:
基本上这个片段应该只抛出 DSError 并告诉我发生了什么以及为什么。问题是 try 块可能会抛出很多其他异常,所以我更喜欢我能做的事情:
try:
v = my_dict[k]
something(v)
except Exception as e:
raise DSError(self, v, e) # Exception chained...
Is this standard pythonic way? I did not see exception chains in other modules so how is that done in Python?
这是标准的pythonic方式吗?我在其他模块中没有看到异常链,那么在 Python 中是如何完成的呢?
采纳答案by phihag
Exception chainingis only available in Python 3, where you can write:
异常链仅在 Python 3 中可用,您可以在其中编写:
try:
v = {}['a']
except KeyError as e:
raise ValueError('failed') from e
which yields an output like
产生的输出像
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
In most cases, you don't even need the from; Python 3 will by default show all exceptions that occured during exception handling, like this:
在大多数情况下,您甚至不需要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
What you can do in Python 2is adding custom attributes to your exception class, like:
您可以在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)
回答by BrenBarn
Is this what you're asking for?
这是你要的吗?
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
If you want to store the original exception object, you can certainly do so in your own exception class's __init__. You might actually want to store the traceback as the exception object itself doesn't provide much useful information about where the exception occurred:
如果要存储原始异常对象,当然可以在自己的异常类的__init__. 您可能实际上想要存储回溯,因为异常对象本身并没有提供关于异常发生位置的很多有用信息:
class MyError(Exception):
def __init__(self, other):
self.traceback = sys.exc_info()
super(MyError, self).__init__(other.message)
After this you can access the tracebackattribute of your exception to get info about the original exception. (Python 3 already provides this as the __traceback__attribute of an exception object.)
在此之后,您可以访问traceback异常的属性以获取有关原始异常的信息。(Python 3 已经提供了 this 作为__traceback__异常对象的属性。)

