首页 文章

python asyncio add_done_callback with async def

提问于
浏览
11

我有两个函数:第一个, 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()

它的工作非常完美 .

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

async def def_b(result):
    next_number = result.result()
    # some asynchronous work on the next_number
    print(next_number + 1)

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

我的问题是 - 是否有可能,如果 def_b 是异步的,如何向 add_done_callback 函数提供 def_b

2 回答

  • -1

    add_done_callback 被认为是"low level"接口 . 使用协同程序时,您可以通过多种方式使用chain them,例如:

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

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

  • 20

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

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

相关问题