python asyncio add_done_callback with async def

Yuv*_*uss 12 python coroutine python-3.x async-await python-asyncio

我有两个函数:第一个def_a是异步函数,第二个是def_b常规函数,调用结果def_a作为add_done_callback函数的回调函数.

我的代码看起来像这样:

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()
Run Code Online (Sandbox Code Playgroud)

它的工作非常完美.

当第二个函数def_b变为异步时,问题就开始了.现在它看起来像这样:

async def def_b(result):
    next_number = result.result()
    # some asynchronous work on the next_number
    print(next_number + 1)
Run Code Online (Sandbox Code Playgroud)

但是现在我无法将它提供给add_done_callback函数,因为它不是常规函数.

我的问题是 - 它是否可能,如果是异步的,我怎么能提供def_badd_done_callback函数def_b

Udi*_*Udi 20

add_done_callback被认为是"低级别"界面.使用协程时,您可以通过多种方式链接它们,例如:

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()
Run Code Online (Sandbox Code Playgroud)

请记住,add_done_callback如果你的未来会引发异常,那么仍会调用回调(但是调用result.result()会引发异常).

  • 在Python 3.7+ https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task中,应使用asyncio.create_task()代替asyncio.ensure_future() (4认同)

use*_*261 5

这仅适用于一个未来的作业,如果您有多个异步作业,它们将相互阻塞,更好的方法是使用 asyncio.as_completed() 迭代未来列表:

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()
Run Code Online (Sandbox Code Playgroud)