web-dev-qa-db-ja.com

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()

ただし、タスクは順番に実行されます。

複数の待機可能オブジェクトを待機する最も簡単な方法は何ですか?なぜ私のアプローチがうまくいかないのですか?

41
Tamas Hegedus

同等のものは 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 も使用できます。

46
Jashandeep Sohi

asyncio.gather() は、順序付けられた結果が必要な場合、asyncio.wait()以外の待機方法の方が良いことに気付きました。

ドキュメントが示すように、asyncio.gather()メソッドからの結果値の順序は、awsのawaitablesの順序に対応しています。ただし、asyncio.wait()からの結果値の順序は同じことを行いません。テストできます。

4