Подождите, пока все завершится (asyncio) - PullRequest
1 голос
/ 18 июня 2019

Я играю с asyncio и не могу достичь того, чего пытаюсь достичь.Вот мой код.

import random
import asyncio

async def my_long_operation(s: str):
    print("Starting operation on", s)
    await asyncio.sleep(3)
    print("End", s)


def random_string(length: int = 10):
    alphabet = \
            [chr(x) for x in range(ord('a'), ord('z') + 1)]

    result = ""
    for i in range(length):
        result += random.choice(alphabet)
    return result


def get_strings(n = 10):
    for i in range(n):
        s = random_string()
        yield s

async def several(loop):
    tasks =list()
    for s in get_strings():
        task = asyncio.create_task(my_long_operation(s))
        asyncio.ensure_future(task, loop = loop)

    print("OK")

loop = asyncio.get_event_loop()
loop.run_until_complete(several(loop))
# loop.run_forever()
loop.close()

Теперь моя проблема заключается в следующем.Я хотел бы запустить все мои my_long_operation одновременно, ожидая, пока все они закончат.Дело в том, что когда я запускаю код, я получаю следующую ошибку:

Task was destroyed but it is pending!
task: <Task pending coro=<my_long_operation() done, defined at test.py:4> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f75274f7168>()]>>

, что, кажется, имеет смысл, поскольку мой сценарий завершился сразу после запуска этих операций (без ожидания их завершения).

Итак, мы подошли к моему актуальному вопросу: как мне это сделать?Как я могу запустить эти задачи и подождать, пока они завершатся, прежде чем завершать сценарий, без использования run_forever (поскольку run_forever никогда не выходит из Python ...)

Спасибо!

1 Ответ

3 голосов
/ 18 июня 2019

ensure_future - это, по сути, метод «поместите его в цикл обработки событий, а затем не мешайте мне». Вместо этого вам нужно дождаться завершения всех ваших асинхронных функций. Для этого используйте asyncio.wait, если вы не особенно заинтересованы в результатах, или asyncio.gather, если хотите получить результаты:

tasks = map(my_long_operation, get_strings())
await asyncio.wait(list(tasks), loop=loop)
print('OK')
...