You want to raise an exception in response to catching a different exception, but wantto include information about both exceptions in the traceback.
>>> def example():
... try:
... int('N/A')
... except ValueError as e:
... raise RuntimeError('A parsing error occurred') from e...
>>>
example()
Traceback (most recent call last):
File "<stdin>", line 3, in example
ValueError: invalid literal for int() with base 10: 'N/A'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):File “”, line 1, in File “”, line 5, in example
RuntimeError: A parsing error occurred>>>
As you can see in the traceback, both exceptions are captured. To catch such an excep‐tion, you would use a normal except statement. However, you can look at the causeattribute of the exception object to follow the exception chain should you wish. Forexample:try:
example()
except RuntimeError as e:
print(“It didn't work:”, e)
if e.cause:print(‘Cause:', e.cause)
An implicit form of chained exceptions occurs when another exception gets raised in‐side an except block. For example:
>>> def example2():
... try:
... int('N/A')
... except ValueError as e:
... print("Couldn't parse:", err)
...
>>>
>>> example2()
Traceback (most recent call last):
File "<stdin>", line 3, in example2
ValueError: invalid literal for int() with base 10: 'N/A'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):File “”, line 1, in File “”, line 5, in example2
NameError: global name ‘err' is not defined>>>
In this example, you get information about both exceptions, but the interpretation is abit different. In this case, the NameError exception is raised as the result of a program‐ming error, not in direct response to the parsing error. For this case, the causeattribute of an exception is not set. Instead, a context attribute is set to the priorexception.If, for some reason, you want to suppress chaining, use raise from None:
>>> def example3():
... try:
... int('N/A')
... except ValueError:
... raise RuntimeError('A parsing error occurred') from None...
>>>
example3()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in example3
RuntimeError: A parsing error occurred
>>>
讨论
In designing code, you should give careful attention to use of the raise statement insideof other except blocks. In most cases, such raise statements should probably bechanged to raise from statements. That is, you should prefer this style:
try:...except SomeException as e:raise DifferentException() from e
The reason for doing this is that you are explicitly chaining the causes together. That is,the DifferentException is being raised in direct response to getting a SomeException. This relationship will be explicitly stated in the resulting traceback.If you write your code in the following style, you still get a chained exception, but it’soften not clear if the exception chain was intentional or the result of an unforeseenprogramming error:
try:...except SomeException:raise DifferentException()
When you use raise from, you’re making it clear that you meant to raise the secondexception.Resist the urge to suppress exception information, as shown in the last example. Al‐though suppressing exception information can lead to smaller tracebacks, it also dis‐cards information that might be useful for debugging. All things being equal, it’s oftenbest to keep as much information as possible.
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。