Комбинируйте awaitables как Promise.all

В асинхронном JavaScript легко запускать задачи параллельно и ждать, пока все они будут завершены с помощью Promise.all:

async function bar(i) {
  console.log('started', i);
  await delay(1000);
  console.log('finished', i);
}

async function foo() {
    await Promise.all([bar(1), bar(2)]);
}

// This works too:
async function my_all(promises) {
    for (let p of promises) await p;
}

async function foo() {
    await my_all([bar(1), bar(2), bar(3)]);
}

Я попытался переписать последнее в python:

import asyncio

async def bar(i):
  print('started', i)
  await asyncio.sleep(1)
  print('finished', i)

async def aio_all(seq):
  for f in seq:
    await f

async def main():
  await aio_all([bar(i) for i in range(10)])

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

Но он выполняет мои задачи последовательно.

Каков самый простой способ подождать нескольких ожидающих? Почему мой подход не работает?

Ответ 1

Эквивалент будет использовать asyncio.wait:

import asyncio

async def bar(i):
  print('started', i)
  await asyncio.sleep(1)
  print('finished', i)

async def main():
  await asyncio.wait([bar(i) for i in range(10)])

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

Почему мой подход не работает?

Потому что, когда вы await каждый элемент в seq, вы блокируете эту сопрограмму. Таким образом, по сути, у вас есть синхронный код, маскирующий как асинхронный. Если вы действительно этого хотели, вы могли бы реализовать свою собственную версию asyncio.wait с помощью loop.create_task или asyncio.ensure_future.

ИЗМЕНИТЬ

Как упоминал Андрей, вы также можете использовать asyncio.gather.

Ответ 2

Я заметил, что asyncio.gather() может быть лучшим способом ожидания, чем asyncio.wait(), если мы хотим упорядоченные результаты.

Как показывают документы, порядок значений результата из метода asyncio.gather() соответствует порядку ожидаемых значений в aws. Однако порядок значений результата из asyncio.wait() не будет делать то же самое. Вы можете проверить это.