python asyncio add_done_callback with async def
add_done_callback
is considered a "low level" interface. When working with coroutines, you can chain them in many ways, for example:
import asyncioasync 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 + 1async def add_success_callback(fut, callback): result = await fut await callback(result) return resultloop = 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()
Keep in mind add_done_callback
will still call the callback if your future raises an exception (but calling result.result()
will raise it).
This only works for one future job, if you have multiple async jobs, they will blocks each other, a better way is using asyncio.as_completed() to iterate future list:
import asyncioasync def __after_done_callback(future_result): # await for something... passasync def __future_job(number): await some_async_work(number) return number + 1loop = asyncio.get_event_loop()tasks = [asyncio.ensure_future(__future_job(x)) for x in range(100)] # create 100 future jobsfor f in asyncio.as_completed(tasks): result = await f await __after_done_callback(result)loop.close()
You can try the aiodag library. It's a very lightweight wrapper around asyncio that abstracts away some of the async plumbing that you usually have to think about. From this example you won't be able to tell that things are running asynchronously since it's just 1 task that depends on another, but it is all running async.
import asynciofrom aiodag import task@taskasync def def_b(result): # some asynchronous work on the next_number print(result + 1)@taskasync def def_a(number): await asyncio.sleep(number) return number + 1async def main(): a = def_a(1) b = def_b(a) # this makes task b depend on task a return await bloop = asyncio.get_event_loop()asyncio.set_event_loop(loop)response = loop.run_until_complete(main())