[Python] Extract specific exception from ExceptionGroup tree

Discussão em 'Python' iniciado por Stack, Novembro 29, 2024.

  1. Stack

    Stack Membro Participativo

    ExceptionGroups in Python contains tuple of unrelated exceptions. Some of these exceptions can be also exception groups. So the specific exception (not the group one) can be nested in several exception groups.

    The except* SpecificException as exc clause match the specific exception regardless how deep it is embedded in exception groups. So far so good.

    The exc variable is for sure an ExceptionGroup (maybe BasicExceptionGroup, but it doesn't matter in my case). The exc.exceptions property can contain the SpecificException but it can also contain only another ExceptionGroup (with another ExceptionGroup inside) and somewhere deep at the bottom there can by the SpecificException.

    What is the Pythonic way to extract this embedded SpecificException from the ExceptionGroup tree?

    I created this example which demonstrate the issue and present my current solution (which is not nice).

    from typing import Iterator, Type

    import trio


    class AlphaExc(Exception):
    alphaAttr: str

    def __init__(self, message: str, alphaAttr: str):
    super().__init__(message)
    self.alphaAttr = alphaAttr


    class BetaExc(Exception):
    pass


    async def alpha():
    raise AlphaExc("Alpha exception", "foo")


    async def beta():
    raise BetaExc("Beta exception")


    # My helper function to extract exceptions from exception group. Is it possible to do it in a more elegant way?
    def extractException[T](excGroup: BaseExceptionGroup, excType: Type[T]) -> Iterator[T]:
    for exc in excGroup.exceptions:
    if isinstance(exc, BaseExceptionGroup):
    yield from extractException(exc, excType)
    else:
    if isinstance(exc, excType):
    yield exc


    async def main():
    try:
    try:
    async with trio.open_nursery() as nursery:
    nursery.start_soon(alpha)
    nursery.start_soon(beta)
    except* (AlphaExc, BetaExc) as exc:
    match, rest = exc.split(AlphaExc) # This is here just to demonstrate embedded exception group
    raise BaseExceptionGroup("My group exception", [match, rest])
    except* AlphaExc as excgroup:
    for ex in extractException(excgroup, AlphaExc):
    print(f"Alpha exception ({type(ex)}): {ex} - {ex.alphaAttr}")


    if __name__ == '__main__':
    trio.run(main)


    So we have an easy way how to detect, that there is some specific exception somewhere in the ExceptionGroup tree, but we have no easy way, how to access such exception(s).

    I wonder, if it is really the best way how to work witch exceptions since Python 3.11 to copy the exctractException function from the example above to each project and use this boilerplate code

    except SpecificException as excgroup:
    for exc in extractException(excgroup, SpecificException):
    # work with exc


    instead of simple

    except SpecificException as exc:
    # work with exc


    Is there some better (simpler) way how to do it?

    Note: I found the similar question here in SO but answers (including the accepted one) does not count with embedded groups.

    Continue reading...

Compartilhe esta Página