非同期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()
ただし、タスクは順番に実行されます。
複数の待機可能オブジェクトを待機する最も簡単な方法は何ですか?なぜ私のアプローチがうまくいかないのですか?
同等のものは 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
すると、そのコルーチンをブロックするためです。したがって、本質的に、非同期としてマスカレードする同期コードがあります。本当にwanted toの場合、asyncio.wait
またはloop.create_task
を使用して、独自のバージョンのasyncio.ensure_future
を実装できます。
[〜#〜] edit [〜#〜]
Andrewが述べたように、 asyncio.gather
も使用できます。
asyncio.gather() は、順序付けられた結果が必要な場合、asyncio.wait()以外の待機方法の方が良いことに気付きました。
ドキュメントが示すように、asyncio.gather()メソッドからの結果値の順序は、awsのawaitablesの順序に対応しています。ただし、asyncio.wait()からの結果値の順序は同じことを行いません。テストできます。