Python异常链接

Aym*_*man 76 python coding-style exception python-2.x

是否有在Python中使用异常链的标准方法?像Java引起的'异常'一样?

这是一些背景知识.

我有一个带有一个主要异常类的模块DSError:

 class DSError(Exception):
     pass
Run Code Online (Sandbox Code Playgroud)

在这个模块的某个地方会有:

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))
Run Code Online (Sandbox Code Playgroud)

基本上这个片段应该只抛出DSError并告诉我发生了什么以及为什么.问题是try块可能会抛出很多其他异常,所以我更喜欢我能做的事情如下:

try:
    v = my_dict[k]
    something(v)
except Exception as e:
    raise DSError(self, v, e)  # Exception chained...
Run Code Online (Sandbox Code Playgroud)

这是标准的pythonic方式吗?我没有在其他模块中看到异常链,那么在Python中如何完成?

phi*_*hag 112

异常链接仅在Python 3中可用,您可以在其中编写:

try:
    v = {}['a']
except KeyError as e:
    raise ValueError('failed') from e
Run Code Online (Sandbox Code Playgroud)

产生类似的输出

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
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,你甚至不需要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
Run Code Online (Sandbox Code Playgroud)

您在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)
Run Code Online (Sandbox Code Playgroud)

  • @timgeb [PEP 3134](https://www.python.org/dev/peps/pep-3134/)有两种链接情况:一种是错误处理代码导致另一个异常被引发,另一种情况是异常被故意翻译成另一个例外.`from e`是故意的情况,并在输出中更改消息,如上面的答案所示. (3认同)
  • 对于python 2,如果想要保存回溯 - 哪一个_must_想要 - [`引发MyError(消息+ u',由'+ repr(cause)引起),None,sys.exc_info()[2]`](http ://stackoverflow.com/a/1350981/281545) (2认同)
  • “在大多数情况下,您甚至不需要 from” 您是否有需要或有用的示例? (2认同)
  • 在我看来,此响应比重复问题的选定答案要好,因为它涵盖了Python3。此外,由于Python 3的回溯已经打印了堆栈中的所有当前异常,因此也指出“ from”是不必要的荣誉。 。 (2认同)

Bre*_*arn 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
Run Code Online (Sandbox Code Playgroud)

如果要存储原始异常对象,则可以在自己的异常类的中进行存储__init__。您可能实际上想存储回溯,因为异常对象本身不提供有关异常发生位置的有用信息:

class MyError(Exception):
    def __init__(self, other):
        self.traceback = sys.exc_info()
        super(MyError, self).__init__(other.message)
Run Code Online (Sandbox Code Playgroud)

之后,您可以访问traceback异常的属性以获取有关原始异常的信息。(Python 3已经提供了它作为__traceback__异常对象的属性。)