本帖最后由 xhz 于 01-03 编辑
引发和处理多个不相关的异常
在有些情况下,有必要报告几个已经发生的异常。这通常是在并发框架中当几个任务并行失败时的情况,但也有其他的用例,有时需要是继续执行并收集多个错误而不是引发第一个异常。
内置的 ExceptionGroup 打包了一个异常实例的列表,这样它们就可以一起被引发。它本身就是一个异常,所以它可以像其他异常一样被捕获。
>>>
def f():
excs = [OSError('error 1'), SystemError('error 2')]
raise ExceptionGroup('there were problems', excs)
f()
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 1, in <module>
| File "<stdin>", line 3, in f
| ExceptionGroup: there were problems
+-+---------------- 1 ----------------
| OSError: error 1
+---------------- 2 ----------------
| SystemError: error 2
+------------------------------------
try:
f()
except Exception as e:
print(f'caught {type(e)}: e')
caught <class 'ExceptionGroup'>: e
通过使用 except* 代替 except ,我们可以有选择地只处理组中符合某种类型的异常。在下面的例子中,显示了一个嵌套的异常组,每个 except* 子句都从组中提取了某种类型的异常,而让所有其他的异常传播到其他子句,并最终被重新引发。
>>>
def f():
raise ExceptionGroup(
"group1",
[
OSError(1),
SystemError(2),
ExceptionGroup(
"group2",
[
OSError(3),
RecursionError(4)
]
)
]
)
try:
f()
except* OSError as e:
print("There were OSErrors")
except* SystemError as e:
print("There were SystemErrors")
There were OSErrors
There were SystemErrors
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 2, in <module>
| File "<stdin>", line 2, in f
| ExceptionGroup: group1
+-+---------------- 1 ----------------
| ExceptionGroup: group2
+-+---------------- 1 ----------------
| RecursionError: 4
+------------------------------------
注意,嵌套在一个异常组中的异常必须是实例,而不是类型。这是因为在实践中,这些异常通常是那些已经被程序提出并捕获的异常,其模式如下:
>>>
excs = []
for test in tests:
try:
test.run()
except Exception as e:
excs.append(e)
if excs:
raise ExceptionGroup("Test Failures", excs)
|