c06_04.rst 2.7 KB
Newer Older
写代码的明哥's avatar
update  
写代码的明哥 已提交
1 2
6.4 【进阶】如何关闭异常自动关联上下文?
========================================
写代码的明哥's avatar
update  
写代码的明哥 已提交
3

update  
王炳明 已提交
4
当你在处理异常时,由于处理不当或者其他问题,再次抛出另一个异常时,往外抛出的异常也会携带原始的异常信息。
写代码的明哥's avatar
update  
写代码的明哥 已提交
5

update  
王炳明 已提交
6
就像这样子。
写代码的明哥's avatar
update  
写代码的明哥 已提交
7 8 9

.. code:: python

update  
王炳明 已提交
10 11 12 13
   try:
       print(1 / 0)
   except Exception as exc:
       raise RuntimeError("Something bad happened")
写代码的明哥's avatar
update  
写代码的明哥 已提交
14

update  
王炳明 已提交
15
从输出可以看到两个异常信息
写代码的明哥's avatar
update  
写代码的明哥 已提交
16 17 18

.. code:: python

update  
王炳明 已提交
19 20 21 22
   Traceback (most recent call last):
     File "demo.py", line 2, in <module>
       print(1 / 0)
   ZeroDivisionError: division by zero
写代码的明哥's avatar
update  
写代码的明哥 已提交
23

update  
王炳明 已提交
24
   During handling of the above exception, another exception occurred:
写代码的明哥's avatar
update  
写代码的明哥 已提交
25

update  
王炳明 已提交
26 27 28 29
   Traceback (most recent call last):
     File "demo.py", line 4, in <module>
       raise RuntimeError("Something bad happened")
   RuntimeError: Something bad happened
写代码的明哥's avatar
update  
写代码的明哥 已提交
30

update  
王炳明 已提交
31 32 33
如果在异常处理程序或 finally
块中引发异常,默认情况下,异常机制会隐式工作会将先前的异常附加为新异常的
``__context__``\ 属性。这就是 Python 默认开启的自动关联异常上下文。
写代码的明哥's avatar
update  
写代码的明哥 已提交
34

update  
王炳明 已提交
35 36
如果你想自己控制这个上下文,可以加个 from 关键字(\ ``from``
语法会有个限制,就是第二个表达式必须是另一个异常类或实例。),来表明你的新异常是直接由哪个异常引起的。
写代码的明哥's avatar
update  
写代码的明哥 已提交
37 38 39

.. code:: python

update  
王炳明 已提交
40
   try:
写代码的明哥's avatar
update  
写代码的明哥 已提交
41
       print(1/0)
update  
王炳明 已提交
42 43
   except Exception as exc:
       raise RuntimeError("Something bad happened") from exc
写代码的明哥's avatar
update  
写代码的明哥 已提交
44

update  
王炳明 已提交
45
输出如下
写代码的明哥's avatar
update  
写代码的明哥 已提交
46 47 48

.. code:: python

update  
王炳明 已提交
49 50 51 52
   Traceback (most recent call last):
     File "demo.py", line 2, in <module>
       print(1 / 0)
   ZeroDivisionError: division by zero
写代码的明哥's avatar
update  
写代码的明哥 已提交
53

update  
王炳明 已提交
54
   The above exception was the direct cause of the following exception:
写代码的明哥's avatar
update  
写代码的明哥 已提交
55

update  
王炳明 已提交
56 57 58 59
   Traceback (most recent call last):
     File "demo.py", line 4, in <module>
       raise RuntimeError("Something bad happened") from exc
   RuntimeError: Something bad happened
写代码的明哥's avatar
update  
写代码的明哥 已提交
60

update  
王炳明 已提交
61
当然,你也可以通过\ ``with_traceback()``\ 方法为异常设置上下文\ ``__context__``\ 属性,这也能在\ ``traceback``\ 更好的显示异常信息。
写代码的明哥's avatar
update  
写代码的明哥 已提交
62 63 64

.. code:: python

update  
王炳明 已提交
65 66 67 68
   try:
       print(1 / 0)
   except Exception as exc:
       raise RuntimeError("bad thing").with_traceback(exc)
写代码的明哥's avatar
update  
写代码的明哥 已提交
69

update  
王炳明 已提交
70
最后,如果我想彻底关闭这个自动关联异常上下文的机制?有什么办法呢?
写代码的明哥's avatar
update  
写代码的明哥 已提交
71

update  
王炳明 已提交
72
可以使用 ``raise...from None``\ ,从下面的例子上看,已经没有了原始异常
写代码的明哥's avatar
update  
写代码的明哥 已提交
73 74 75

.. code:: python

update  
王炳明 已提交
76 77 78 79 80 81 82 83 84 85 86 87
   $ cat demo.py
   try:
       print(1 / 0)
   except Exception as exc:
       raise RuntimeError("Something bad happened") from None
   $
   $ python demo.py
   Traceback (most recent call last):
     File "demo.py", line 4, in <module>
       raise RuntimeError("Something bad happened") from None
   RuntimeError: Something bad happened
   (PythonCodingTime)