Implement PEP 654: Exception Groups #89455
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
assignee = 'https://github.com/iritkatriel' closed_at = <Date 2022-01-06.19:06:15.397> created_at = <Date 2021-09-26.12:07:11.663> labels = ['interpreter-core', '3.11', 'type-feature', 'library', 'docs'] title = 'Implement PEP 654: Exception Groups' updated_at = <Date 2022-01-06.19:06:15.396> user = 'https://github.com/iritkatriel'
activity = <Date 2022-01-06.19:06:15.396> actor = 'iritkatriel' assignee = 'iritkatriel' closed = True closed_date = <Date 2022-01-06.19:06:15.397> closer = 'iritkatriel' components = ['Documentation', 'Interpreter Core', 'Library (Lib)'] creation = <Date 2021-09-26.12:07:11.663> creator = 'iritkatriel' dependencies =  files =  hgrepos =  issue_num = 45292 keywords = ['patch'] message_count = 12.0 messages = ['402661', '404837', '405773', '406266', '406400', '408549', '408557', '408559', '408560', '408589', '408590', '409898'] nosy_count = 5.0 nosy_names = ['gvanrossum', 'Mark.Shannon', 'xtreak', 'erlendaasland', 'iritkatriel'] pr_nums = ['28569', '29207', '29545', '29581', '30158'] priority = 'normal' resolution = 'fixed' stage = 'resolved' status = 'closed' superseder = None type = 'enhancement' url = 'https://bugs.python.org/issue45292' versions = ['Python 3.11']
The text was updated successfully, but these errors were encountered:
The tests emit some deprecation warnings :
PYTHONWARNINGS=always ./python -Wall -m test test_exception_group 0:00:00 load avg: 0.39 Run tests sequentially 0:00:00 load avg: 0.39 [1/1] test_exception_group /home/karthikeyan/stuff/python/cpython/Lib/test/test_exception_group.py:41: DeprecationWarning: invalid escape sequence '\(' MSG = 'second argument \(exceptions\) must be a sequence' /home/karthikeyan/stuff/python/cpython/Lib/test/test_exception_group.py:47: DeprecationWarning: invalid escape sequence '\(' MSG = 'second argument \(exceptions\) must be a non-empty sequence' /home/karthikeyan/stuff/python/cpython/Lib/test/test_exception_group.py:52: DeprecationWarning: invalid escape sequence '\(' MSG = ('Item [0-9]+ of second argument \(exceptions\)'
== Tests result: SUCCESS ==
1 test OK.
Total duration: 51 ms
PR 29581 resulted in a 1% slowdown, which is not terrible, but code not using except* should not be slowed down at all.
IMO, the way to avoid the slowdown is to implement except* using the existing instruction set (perhaps with a few minor additions)
We already implement try-finally, named except blocks and with statements without any complex bytecodes (except perhaps WITH_EXCEPT_START).
These used to involve a lot of state and more complex bytecodes. So it is possible to make these simplifications,
There are a number of techniques we can use:
If any state is needed, push it to the stack as we do with
It may be too late for this advice, but if I were writing the
The PR adds two new opcodes. Let's start with the simpler of the two - JUMP_IF_NOT_EG_MATCH. This is the exception-group variation on JUMP_IF_NOT_EXC_MATCH.
JUMP_IF_NOT_EXC_MATCH checks for a match by checking if the exception is of the given type. The result is boolean.
JUMP_IF_NOT_EG_MATCH checks for a matching by calling .split() on the exception group. The result is two exception groups (the matching part and the non-matching part).
Can we do this without a new opcode?
The second opcode that the PR adds is PREP_RERAISE_STAR.
This opcode takes a list that contains:
It constructs the exception group that needs to be raised at the end. This is done through a fairly complex operation on the BaseExceptionGroup, which merges the re-raised exceptions into the same nesting structure they had in the original exception group, so that
is equivalent to just 'raise eg'.
Is there any overlap with existing opcodes?
The way these two opcodes are combined by the compiler to implement except* is described in the pseudo code here:
except* uses JUMP_IF_NOT_EG_MATCH. The excepts (not-) that collect exceptions raised in the except clauses are virtual.
The do_reraise_star at the end is PREP_RERAISE_STAR followed by POP_EXCEPT_AND_RERAISE.
Fix an uninitialized bool in exception print context. `struct exception_print_context.need_close` was uninitialized. Found by oss-fuzz in a test case running under the undefined behavior sanitizer. https://oss-fuzz.com/testcase-detail/6217746058182656 ``` Python/pythonrun.c:1241:28: runtime error: load of value 253, which is not a valid value for type 'bool' #0 0xbf2203 in print_chained cpython3/Python/pythonrun.c:1241:28 #1 0xbea4bb in print_exception_cause_and_context cpython3/Python/pythonrun.c:1320:19 #2 0xbea4bb in print_exception_recursive cpython3/Python/pythonrun.c:1470:13 #3 0xbe9e39 in _PyErr_Display cpython3/Python/pythonrun.c:1517:9 ``` Pretty obvious what the ommission was upon code inspection.