gpt4 book ai didi

没有参数的 Python 'raise' : what is "the last exception that was active in the current scope"?

转载 作者:太空狗 更新时间:2023-10-29 19:26:06 32 4
gpt4 key购买 nike

Python 的文档说:

If no expressions are present, raise re-raises the last exception that was active in the current scope.

(Python 3:https://docs.python.org/3/reference/simple_stmts.html#raise;Python 2.7:https://docs.python.org/2.7/reference/simple_stmts.html#raise。)

但是,“最后激活”的概念似乎已经改变。见证以下代码示例:

#
from __future__ import print_function
import sys
print('Python version =', sys.version)

try:
raise Exception('EXPECTED')
except:
try:
raise Exception('UNEXPECTED')
except:
pass
raise # re-raises UNEXPECTED for Python 2, and re-raises EXPECTED for Python 3

这导致了我对 Python 2 没有预料到的结果:

Python version = 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)]
Traceback (most recent call last):
File "./x", line 10, in <module>
raise Exception('UNEXPECTED')
Exception: UNEXPECTED

但在 Python 3 中有预期的(我)结果:

Python version = 3.6.8 (default, Feb 14 2019, 22:09:48)
[GCC 7.4.0]
Traceback (most recent call last):
File "./x", line 7, in <module>
raise Exception('EXPECTED')
Exception: EXPECTED

Python version = 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)]
Traceback (most recent call last):
File "./x", line 7, in <module>
raise Exception('EXPECTED')
Exception: EXPECTED

那么“最后一个……活跃的”是什么意思呢?是否有关于此重大更改的一些文档?或者这是一个 Python 2 错误?

更重要的是:在 Python 2 中实现此功能的最佳方式是什么? (最好让代码在 Python 3 中继续工作。)


注意如果将代码更改为

#
from __future__ import print_function
import sys
print('Python version =', sys.version)

def f():
try:
raise Exception('UNEXPECTED')
except:
pass

try:
raise Exception('EXPECTED')
except:
f()
raise # always raises EXPECTED

然后事情也开始适用于 Python 2:

Python version = 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)]
Traceback (most recent call last):
File "./x", line 13, in <module>
raise Exception('EXPECTED')
Exception: EXPECTED

我正在考虑切换到那个...

最佳答案

与其说 Python 2 的行为是一个错误,不如说是一个设计缺陷。它在 Python 3.0 中通过添加异常链功能得到解决。最接近此更改文档的内容可以在 PEP 3134 -- Exception Chaining and Embedded Tracebacks 中找到。动机:

During the handling of one exception (exception A), it is possible that another exception (exception B) may occur. In today's Python (version 2.4), if this happens, exception B is propagated outward and exception A is lost.

这正是您在 2.7 中看到的:EXPECTED (A) 丢失,因为 UNEXPECTED (B) 出现并覆盖了它。借助 Python 3 中较新的异常链接功能,可以通过异常实例上的 __cause____context__ 属性保留两个错误的完整上下文。

对于更直接的交叉兼容解决方法,我鼓励您手动保留引用,明确显示重新引发的错误,并且像往常一样避免裸露的 except 语句(它们总是太宽泛):

try:
raise Exception('EXPECTED')
except Exception as err_expected:
try:
raise Exception('UNEXPECTED')
except Exception as err_unexpected:
pass
raise err_expected

如果您希望以交叉兼容的方式抑制异常链接功能,您可以通过在重新引发之前设置 err_expected.__cause__ = None 来实现。

关于没有参数的 Python 'raise' : what is "the last exception that was active in the current scope"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56429727/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com