1. ホーム
  2. python

[解決済み] Promise.allのようなawaitableを組み合わせる。

2023-08-19 01:37:03

質問

非同期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()

しかし、それは私のタスクを順次実行します。

複数のawaitableをawaitする最も簡単な方法は何ですか? なぜ私のやり方はうまくいかないのでしょうか?

どのように解決するのですか?

同等な方法として asyncio.gather :

import asyncio

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

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

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

なぜ私のやり方はうまくいかないのか?

なぜなら、あなたが await の各項目は seq の各項目で、そのコルーチンをブロックしています。つまり、本質的には同期的なコードが非同期的なコードに見せかけられているのです。もし、本当に が欲しいなら を実装することができます。 asyncio.gather を使って loop.create_task または asyncio.ensure_future .

EDIT

元の回答では、下位レベルの asyncio.wait .