Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The except* clause is a control flow mechanism introduced in Python 3.11 designed to handle ExceptionGroup and BaseExceptionGroup objects. Unlike the traditional except clause, which catches and handles a single exception, except* performs type-based matching and extraction on an exception tree, allowing multiple except* blocks to execute sequentially if their specified exception types are present within the group.
try:
    raise ExceptionGroup(
        "Multiple errors occurred",
        [ValueError("bad value"), TypeError("bad type"), ValueError("another bad value")]
    )
except* ValueError as e:
    # Executes first. 'e' is an ExceptionGroup containing the two ValueErrors.
    print(f"Handled ValueErrors: {e.exceptions}")
except* TypeError as e:
    # Executes second. 'e' is an ExceptionGroup containing the single TypeError.
    print(f"Handled TypeErrors: {e.exceptions}")

Core Mechanics

Exception Splitting When an exception group is raised, the Python interpreter evaluates it against the except* clauses. If a clause matches one or more exceptions within the group, the interpreter “splits” the group. The matched exceptions are extracted and passed into the except* block, while the unmatched exceptions are retained in a new exception group to be evaluated by subsequent except* clauses. Multiple Executions Because of the splitting mechanism, multiple except* clauses attached to a single try block can execute during a single exception handling phase. This is a fundamental departure from standard except clauses, where execution halts after the first matching block. Alias Binding The object bound to the target alias (e.g., as e) is never a direct instance of the matched exception. Instead, it is an exception group (ExceptionGroup or BaseExceptionGroup, depending on whether the matched exceptions include a BaseException that is not an Exception). This new group contains only the exceptions from the original group that matched the clause’s type, preserving the original nesting structure. Implicit Re-raising If the original group contains exceptions that do not match any of the provided except* clauses, those remaining exceptions are automatically re-raised after all except* blocks have been evaluated. They are re-raised as an ExceptionGroup, or as a BaseExceptionGroup if any of the unmatched exceptions inherit directly from BaseException (e.g., KeyboardInterrupt).

Control Flow Interruptions

The except* clause introduces unique control flow mechanics when execution is interrupted from inside the block:
  • Raising Exceptions: If a new exception is raised inside an except* block, it does not immediately propagate and halt the evaluation of the original exception group. Instead, the newly raised exception is suspended. Subsequent except* clauses continue to evaluate the remaining unmatched exceptions. Once all clauses are evaluated, all suspended exceptions raised from within the except* blocks are combined with any remaining unmatched exceptions from the original group and raised together as a new exception group.
  • return, break, and continue: If an except* block executes a return, break, or continue statement, the exception handling phase is immediately aborted. Subsequent except* clauses are skipped, and any remaining unmatched exceptions from the original group are silently dropped.

Syntax Rules and Constraints

  • Mutual Exclusivity: You cannot mix except and except* clauses on the same try block. A try block must use exclusively one or the other.
# SyntaxError: cannot have both 'except' and 'except*' on the same 'try'
try:
    ...
except ValueError:
    ...
except* TypeError:
    ...
  • Subclass Matching: Like standard except, except* respects the class hierarchy. except* OSError: will match and extract FileNotFoundError, PermissionError, and any other OSError subclasses present in the group.
  • Naked Exceptions: If a standard, single exception (a “naked” exception, not an exception group) is raised inside a try block monitored by except*, it is evaluated against the clauses. If it matches an except* clause, it is dynamically wrapped in an exception group (ExceptionGroup, or BaseExceptionGroup if it is a BaseException like SystemExit) strictly for the purpose of binding to the alias. If the naked exception does not match any except* clause, it propagates outward as the original naked exception, not as an exception group.
  • Catching the Group: You cannot use except* ExceptionGroup: or except* BaseExceptionGroup:. The except* syntax is designed to match the types of the exceptions contained within the group, not the group container itself. To catch all exceptions within a group, you must use except* Exception: or except* BaseException:.
Master Python with Deep Grasping Methodology!Learn More