Задание AsyncIO не заканчивается, когда метод по существу завершен - PullRequest
1 голос
/ 31 марта 2019

Я пытаюсь запустить сопрограмму и ждать ее возвращаемого значения с помощью eventloop.run_until_complete, но я заметил, что run_until_complete возвращает много времени после того, как сопрограмма по существу завершена (в конечном итоге она возвращается).

Вот фрагмент того, что я пробовал:

def wait_for_message(timeout_sec):
    loop = asyncio.get_event_loop()
    fut = asyncio.ensure_future(_receive_pb_msgs(timeout_sec))
    res = loop.run_until_complete(fut)

    return res

async def _receive_msgs(timeout_sec):
    start_time = time()
    current_time = start_time
    text = None
    async with wsc.connect("URL") as ws:
        while current_time - start_time <= timeout_sec:
            jdata = await ws.recv()
            msg = json.loads(jdata)
            if some_criteria:
                text = msg
                break

            current_time = time()
            await sleep(.1)
    print(f"return: {current_time - start_time}")
    return text


if __name__ == "__main__":
    s = time()
    msg = wait_for_message(10)
    e = time()
    print(f"actual: {e - s})

и вывод:

return: 6.387637138366699
actual: 38.61859059333801

Как видите, цикл занимает около 38 секунд, даже если функция завершается через 6 секунд.

Есть что-то, чего я здесь не хватает? Спасибо!

1 Ответ

2 голосов
/ 31 марта 2019
  1. break на some_criteria оставит current_time устаревшим (поскольку текущая итерация не будет учитываться)
  2. некоторые async with выходящие очистки могут произойти после сохранения current_time в прошлый раз

Вы должны обязательно поместить строку current_time = time() прямо перед печатью return:.Это, вероятно, исправит несоответствие.

...