J'ai 2 fonctions: la première, def_a
, est une fonction asynchrone et la seconde est def_b
qui est une fonction régulière et appelée avec le résultat de def_a
comme rappel avec le add_done_callback
fonction.
Mon code ressemble à ceci:
import asyncio
def def_b(result):
next_number = result.result()
# some work on the next_number
print(next_number + 1)
async def def_a(number):
await some_async_work(number)
return number + 1
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(def_a(1))
task.add_done_callback(def_b)
response = loop.run_until_complete(task)
loop.close()
Et ça marche parfaitement.
Le problème a commencé lorsque la deuxième fonction, def_b
, est devenu asynchrone. Maintenant, cela ressemble à ceci:
async def def_b(result):
next_number = result.result()
# some asynchronous work on the next_number
print(next_number + 1)
Mais maintenant, je ne peux pas le fournir au add_done_callback
fonction, car ce n'est pas une fonction régulière.
Ma question est: est-ce possible et comment puis-je fournir def_b
à la add_done_callback
fonction si def_b
est asynchrone?
add_done_callback
Est considéré comme une interface "de bas niveau". Lorsque vous travaillez avec des coroutines, vous pouvez les enchaîner de plusieurs façons, par exemple:
import asyncio
async def my_callback(result):
print("my_callback got:", result)
return "My return value is ignored"
async def coro(number):
await asyncio.sleep(number)
return number + 1
async def add_success_callback(fut, callback):
result = await fut
await callback(result)
return result
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coro(1))
task = add_success_callback(task, my_callback)
response = loop.run_until_complete(task)
print("response:", response)
loop.close()
Gardez à l'esprit que add_done_callback
Appellera toujours le rappel si votre futur déclenche une exception (mais appeler result.result()
la déclenchera).
Cela ne fonctionne que pour un futur travail, si vous avez plusieurs travaux asynchrones, ils se bloqueront mutuellement, une meilleure façon est d'utiliser asyncio.as_comleted () pour itérer la future liste:
import asyncio
async def __after_done_callback(future_result):
# await for something...
pass
async def __future_job(number):
await some_async_work(number)
return number + 1
loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(__future_job(x)) for x in range(100)] # create 100 future jobs
for f in asyncio.as_completed(tasks):
result = await f
await __after_done_callback(result)
loop.close()