Skip to content
This repository was archived by the owner on Apr 10, 2022. It is now read-only.
This repository was archived by the owner on Apr 10, 2022. It is now read-only.

Introducing try..catch #3

Closed
Closed
@gvanrossum

Description

@gvanrossum

If we find we really need new syntax to flag that people have thought about the consequences of multi-exceptions, we could switch the existing try..except syntax to try..catch. It seems most other languages use the latter keyword anyway.

Syntax

The syntax would just replace except with catch, leaving everything else the same.

We have the option however of disallowing catch: (i.e. with no exception, the catch-all block) -- forcing people (and automatic translators) to write catch BaseException:.

Note that catch would have to be a soft keyword (supported by the new PEG parser, see PEP 617), since there are plenty of other uses of catch in existing code that we don't want to break.

Transition

The transition plan would be that try..exept will eventually be removed from the language. There would be three stages:

  1. try..catch and try..except can both be used.
  2. try..except works but gives a deprecation warning.
  3. try..except stops working.

Possibly stage 2 can be split and try..except inside async functions can be deprecated sooner than in other contexts.

During stages 1 and 2, each try statement must use either catch or except -- you cannot have both catch and except blocks in the same statement. (But you can have them in the same file.)

Semantics

When the raised exception is not a multi-exception the semantics of try..catch is the same as for try..except.

When the raised exception is a multi-error the semantics change.

Basically when a multi-error contains different exception types it is possible that more than one catch block runs. E.g.

try:
    raise MultiError([ValueError(), ZeroDivisionError(), RuntimeError()])  # or whatever
catch ValueError:
    print("VE")
catch RuntimeError:
    print("RE")

would print "VE" and "RE" and then raise (bubble up) RuntimeError() (or MultiError([RuntimeError()]).

If there's an else block it only gets run if no exceptions were raised in the first place.

If there's a finally block it gets run after all catch blocks (if any) have run, before bubbling up the unhandled exceptions (if any).

The order in which the exceptions in the multi-error are handled is just the order in which the MultiError object regurgitates them.

Multiple exceptions of the same type

This is an open issue.

What if the try block raises MultiError([ValueError("A"), ValueError("B")])? We could define different semantics.

Note that there would also be a question about two different exception classes that derive from the same base class, where the catch class specifies that base (or ultimately catch BaseException). So we cannot rely on MultiError to split exceptions based on class before we start matching exceptions to catch blocks.

TO BE CONTINUED IN A LATER COMMENT (I deleted some meta-comments related to this.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions