Handle SystemExit with asyncio.gather correctly

343 Views Asked by At

I want to run asyncio.gather with some awaitables, which can raise SystemExit.

import asyncio


async def func(t):
    await asyncio.sleep(t)
    raise SystemExit('Err')


async def main():
    tasks = [asyncio.ensure_future(func(t)) for t in range(0, 3)]
    print('Starting gather')
    try:
        await asyncio.gather(*tasks, return_exceptions=True)
    except BaseException:
        pass
    print('Gather returned')
    for t in tasks:
        if not t.done():
            t.cancel()
        try:
            await t
        except BaseException:
            pass
    await asyncio.sleep(1)


asyncio.run(main())

The exit code of the snippet is 1, because asnycio.run will raise the SystemExit again in its internal cancel_all_tasks, which itself calls tasks.gather. How can I prevent this behavior, so the snippet will have an exit code of 0 (without catching the exception from asyncio.run).

Is there a way to prevent cancel_all_tasks from seeing my already canceled tasks? IS there another solution then wrapping the SystemExit in func?

0

There are 0 best solutions below