2

Consider the following code:

import trio


async def broken_fn():
    await trio.sleep(4)
    print(1 / 0)


async def worker_fn():
    while True:
        print("working...")
        await trio.sleep(1)


async def main():
    async with trio.open_nursery() as nursery:
        nursery.start_soon(broken_fn)
        nursery.start_soon(worker_fn)


trio.run(main)

How do I prevent the exception raised by broken_fn to abort its siblings in the nursery without touching the definition of broken_fn? Is the following the best way?

async def main():
    async def supress(fn):
        try:
            await fn()
        except Exception as e:
            print(f"caught {e}!")

    async with trio.open_nursery() as nursery:
        nursery.start_soon(supress, broken_fn)
        nursery.start_soon(worker_fn)

Do I have any other options?

Wildebeest
  • 23
  • 3

1 Answers1

4

There is no mechanism in start_soon() to ignore exceptions, if that's what you're looking for.

You could also do this in a generic fashion, so as not to build wrappers for each individual function:

from contextlib import suppress
from functools import wraps
from typing import Callable

def suppressed(func: Callable, *exceptions: BaseException):
    @wraps(func)
    async def wrapper(*args, **kwargs):
        with suppress(*exceptions):
            return await func(*args, **kwargs)
        
    return wrapper

Then:

async with trio.open_nursery() as nursery:
    nursery.start_soon(suppressed(broken_fn, Exception))
    nursery.start_soon(worker_fn)
Alex Grönholm
  • 4,109
  • 20
  • 28