Как вырваться из asyncio coroutine без использования оператора "return"?


Я немного затрудняюсь решить, как выйти из этой сопрограммы, если оператор except поймает. Обычно я просто использую:

def f(x):
    try:
        foo_var = next(a_volitile_generator(x))
    except Exception:
        print('it broked')
        return
    yield foo_var

Однако! Я собираюсь породить газиллион этих генераторных функций, сделать их сопрограммами и, наконец, Futureиз них и загрузить их в цикл событий. Вот в чем проблема:

loop = asyncio.get_event_loop()
queue = asyncio.Queue(maxsize=100)

async def f(x, result_queue, *, loop=loop):
    while _some_condition() is True:
        try:
            foo_var = await a_volitile_async_generator(x)
        except Exception:
            print('it broked')
            # HELP BELOW
            raise StopAsyncIteration # <--ONLY OPTION????????
        await result_queue.put(foo_var)

Возврат чего-либов цикл событий -это нет-нет в asyncio, потому что вы все сломаете...даже если это значение равно None.

В сторону исходя из этого, давайте также скажем, что я хотел бы избежать повышения StopAsyncIteration...Я пытаюсь понять, является ли это единственным способом сделать это или у меня есть другие варианты:

2 2

2 ответа:

Как упомянуто @dirn в комментариях, вы можете заменить свою raise StopAsyncIteration строку на простую break:

async def f(x, result_queue, *, loop=loop):
    while _some_condition() is True:
        try:
            foo_var = await a_volitile_async_generator(x)
        except Exception:
            print('it broked')
            break
        await result_queue.put(foo_var)

Джонни, я думаю, ты делаешь что-то не так.

yield from a_volitile_async_generator(x)

Если a_volitile_async_generator является реальным асинхронным генератором, он не будет работать: Вы не можете использовать yield from вместе с ним.