Now Python >= 3.11 has ExceptionGroup
, what do you think of raising such an exception
when leaving an ExitStack
in case of errors in callbacks ?
This would allow someone to get all exceptions, not only the last one.
Example of current implementation:
from contextlib import ExitStack
def fail1():
raise RuntimeError("fail1")
def fail2():
raise RuntimeError("fail2")
with ExitStack() as es:
es.callback(fail1)
es.callback(fail2)
Results in:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/matias/miniconda3/envs/bec/lib/python3.11/contextlib.py", line 603, in __exit__
raise exc_details[1]
File "/home/matias/miniconda3/envs/bec/lib/python3.11/contextlib.py", line 587, in __exit__
if cb(*exc_details):
^^^^^^^^^^^^^^^^
File "/home/matias/miniconda3/envs/bec/lib/python3.11/contextlib.py", line 469, in _exit_wrapper
callback(*args, **kwds)
File "<stdin>", line 2, in fail1
RuntimeError: fail1
There is no way to know an error occured while calling fail2
With the proposed change, the code above would result in:
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 1, in <module>
| File "/home/matias/miniconda3/envs/bec/lib/python3.11/contextlib.py", line 607, in __exit__
| raise ExceptionGroup("Exceptions occured in ExitStack callbacks", excs)
| ExceptionGroup: Exceptions occured in ExitStack callbacks (2 sub-exceptions)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/home/matias/miniconda3/envs/bec/lib/python3.11/contextlib.py", line 587, in __exit__
| if cb(*exc_details):
| ^^^^^^^^^^^^^^^^
| File "/home/matias/miniconda3/envs/bec/lib/python3.11/contextlib.py", line 469, in _exit_wrapper
| callback(*args, **kwds)
| File "<stdin>", line 2, in fail2
| RuntimeError: fail2
+---------------- 2 ----------------
| Traceback (most recent call last):
| File "/home/matias/miniconda3/envs/bec/lib/python3.11/contextlib.py", line 587, in __exit__
| if cb(*exc_details):
| ^^^^^^^^^^^^^^^^
| File "/home/matias/miniconda3/envs/bec/lib/python3.11/contextlib.py", line 469, in _exit_wrapper
| callback(*args, **kwds)
| File "<stdin>", line 2, in fail1
| RuntimeError: fail1
+------------------------------------
I find it much better. What do you think ?