exceptiongroup icon indicating copy to clipboard operation
exceptiongroup copied to clipboard

Proposal: native exception handling API

Open maxfischer2781 opened this issue 5 years ago • 2 comments
trafficstars

As an alternative or addition to #5, it is possible to use Python's try-except natively:

try:
    async with something:
        something.raise_concurrent()
except MultiError[A]:
     print("Handled concurrent A")
except MultiError[A, B] as err:
     print("Handled concurrent A and B")
except (MultiError[B], MultiError[C]) as err:
     print("Handled concurrent B or C:", err)
except A:
    print("Handled non-concurrent A")

Note: See original comment in trio/#611 for further context and details not related to the except API itself. The approach has been implemented and tested in the usim simulator.


Pros:

The primary advantage here is that exception group handling follows the same rules as regular exception handling. The sequence of handlers, how handlers are executed, and the scope in which they are executed, are the same.

Users do not have to import additional tools for catching exceptions (splitting etc. is not part of this proposal). Everything can be encapsulated in the MultiError/ExceptionGroup. The only visible "trick" is templating via Cls[ExcA, ExcB], which should be common knowledge due to typing.

Cons:

There are no native "subhandlers". Handling a MultiError[A, B] just provides that kind of object; separating the handling of its A and B components must be done manually. Handling sub-exceptions may-or-may-not be part of the MultiError itself, but requires nesting inside the except class.

The implementation is more complicated in that a metaclass is required: A clause except A: uses issubclass(type(exception), A), which requires implementing type(A).__subclasscheck__. Outwards simplicity is traded for inner complexity.

maxfischer2781 avatar Jun 19 '20 06:06 maxfischer2781

Do except blocks use subclasscheck? I have a vague memory of them maybe skipping that for speed.

(I think the larger issue is whether these semantics are helpful, but the technical details matter too.)

On Thu, Jun 18, 2020, 23:42 Max Fischer [email protected] wrote:

As an alternative or addition to #5 https://github.com/python-trio/exceptiongroup/issues/5, it is possible to use Python's try-except natively:

try: async with something: something.raise_concurrent()except MultiError[A]: print("Handled concurrent A")except MultiError[A, B] as err: print("Handled concurrent A and B")except MultiError[B], MultiError[C] as err: print("Handled concurrent B or C:", err)except A: print("Handled non-concurrent A")

Note: See original comment in trio/#611 https://github.com/python-trio/trio/issues/611#issuecomment-527414799 for further context and details not related to the except API itself. The approach has been implemented and tested in the usim simulator https://github.com/MaineKuehn/usim.

Pros:

The primary advantage here is that exception group handling follows the same rules as regular exception handling. The sequence of handlers, how handlers are executed, and the scope in which they are executed, are the same.

Users do not have to import additional tools for catching exceptions (splitting etc. is not part of this proposal). Everything can be encapsulated in the MultiError/ExceptionGroup. The only visible "trick" is templating via Cls[ExcA, ExcB], which should be common knowledge due to typing. Cons:

There are no native "subhandlers". Handling a MultiError[A, B] just provides that kind of object; separating the handling of its A and B components must be done manually. Handling sub-exceptions may-or-may-not be part of the MultiError itself, but requires nesting inside the except class.

The implementation is more complicated in that a metaclass is required: A clause except A: uses issubclass(type(exception), A), which requires implementing type(A).subclasscheck. Outwards simplicity is traded for inner complexity.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/python-trio/exceptiongroup/issues/20, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEU42CVAC52XV7KRYHNTFLRXMCGTANCNFSM4OCOIVEA .

njsmith avatar Jun 19 '20 06:06 njsmith

Yes, except blocks use __subclasscheck__. As said, we are using that already and the approach is working.

I'm currently preparing a draft PR so that things can be discussed with code samples as well.

I'd love to get feedback on the usability.

maxfischer2781 avatar Jun 19 '20 06:06 maxfischer2781