web-dev-qa-db-fra.com

Combinez des objets attendus comme Promise.all

En JavaScript asynchrone, il est facile d'exécuter des tâches en parallèle et d'attendre qu'elles se terminent toutes en utilisant 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)]);
}

J'ai essayé de réécrire ce dernier en 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()

Mais il exécute mes tâches de manière séquentielle.

Quelle est la manière la plus simple d'attendre plusieurs attentes? Pourquoi mon approche ne fonctionne-t-elle pas?

41
Tamas Hegedus

L'équivalent utiliserait 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()

Pourquoi mon approche ne fonctionne-t-elle pas?

Parce que lorsque vous await chaque élément dans seq, vous bloquez cette coroutine. Donc, en substance, vous avez du code synchrone se faisant passer pour asynchrone. Si vous avez vraiment voulu à, vous pouvez implémenter votre propre version de asyncio.wait en utilisant loop.create_task ou asyncio.ensure_future.

[~ # ~] modifier [~ # ~]

Comme Andrew l'a mentionné, vous pouvez également utiliser asyncio.gather .

46
Jashandeep Sohi

J'ai remarqué que asyncio.gather () peut être une meilleure façon d'attendre autre que asyncio.wait () si nous voulons des résultats ordonnés.

Comme l'indique la documentation, l'ordre des valeurs de résultat de la méthode asyncio.gather () correspond à l'ordre des attentes dans aws. Cependant, l'ordre des valeurs de résultat de asyncio.wait () ne fera pas la même chose. Vous pouvez le tester.

4
请叫我小马哥