从任务创建函数返回异步回调结果

时间:2019-08-29 14:29:55

标签: python-3.x asynchronous callback python-asyncio

我正在尝试包装一个异步函数,以便可以在不将asyncio导入某些文件的情况下使用它。最终目标是使用异步函数,但能够正常调用它们并获取结果。

如何从回调函数printing(task)访问结果并将其用作我的make_task(x)函数的返回?

MWE:

#!/usr/bin/env python3.7

import asyncio

loop = asyncio.get_event_loop()

def make_task(x):   # Can be used without asyncio
    task = loop.create_task(my_async(x))
    task.add_done_callback(printing)
    # return to get the 

def printing(task):
    print('sleep done: %s' % task.done())
    print('results: %s' % task.result())
    return task.result()    # How can i access this return?

async def my_async(x):  # Handeling the actual async running
    print('Starting my async')
    res = await my_sleep(x)
    return res  # The value I want to ultimately use in the real callback

async def my_sleep(x):
    print('starting sleep for %d' % x)
    await asyncio.sleep(x)
    return x**2

async def my_coro(*coro):
    return await asyncio.gather(*coro)

val1 = make_task(4)
val2 = make_task(5)
loop.run_until_complete(my_coro(asyncio.sleep(6)))

print(val1)
print(val2)

2 个答案:

答案 0 :(得分:0)

您可以使printing为协程,而await为原始协程,例如my_async,而不使用回调。 make_task然后可以从printing(my_async(...))中创建任务,这将使printing的返回值可用作任务结果。换句话说,要从printing中返回一个值,只需-将其返回。

例如,如果您这样定义make_taskprinting,而使程序的其余部分保持不变:

def make_task(x):
    task = loop.create_task(printing(my_async(x)))
    return task

async def printing(coro):
    coro_result = await coro
    print('sleep done')
    print('results: %s' % coro_result)
    return coro_result

结果输出为:

Starting my async
starting sleep for 4
Starting my async
starting sleep for 5
sleep done
results: 16
sleep done
results: 25
<Task finished coro=<printing() done, defined at result1.py:11> result=16>
<Task finished coro=<printing() done, defined at result1.py:11> result=25>

答案 1 :(得分:0)

如果我正确理解,您想使用异步函数,但不想在顶级代码中编写async / await

如果是这种情况,恐怕asyncio无法实现。 asyncio希望您在发生异步操作的任何地方编写async / await,这是有意的:强制明确标记可能的上下文切换的位置是asyncio的一种抗击方式与并发相关的问题(否则很难解决)。阅读this answer了解更多信息。

如果您仍然希望拥有异步内容并“像往常一样使用”代码,请查看gevent之类的替代解决方案。