我有一个装饰器,它装饰协程函数并将协程返回的值分配给 future 的实例。
import asyncio
import functools
def ensure_prepare(future):
async def decorator(asyncfunc):
@functools.wraps(asyncfunc)
async def wrapper(*args, **kwargs):
future.set_result(await asyncfunc(*args, **kwargs))
return future
return wrapper
return decorator
演示:
>>> future = asyncio.Future()
>>>
>>> @ensure_prepare(future)
... async def check_sanity():
... return 9
...
>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(check_sanity)
<function check_sanity at 0x7f935300a158>
>>> _()
<coroutine object check_sanity at 0x7f934f78a728>
>>> loop.run_until_complete(_)
<Future finished result=9>
>>> _.result()
9
如您所见,我需要运行两次事件循环才能获得 future 的结果。有没有办法让事件循环在第一次运行后返回值?我不想在我的代码中等待并将结果(函数)分配给一个名称。
最佳答案
在您的代码中,您已将 decorator
包装器设为 async
,这不是您想要的,这意味着无论何时您使用包装器,它都会返回一个协程将生成包装函数的对象:
>>> future = asyncio.Future()
>>> @ensure_prepare(future)
async def chech_sanity():
return 9
>>> check_sanity
<coroutine object ensure_prepare.<locals>.decorator at 0x10572f4c0>
>>> check_sanity.send(None) #advance coroutine
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
check_sanity.send(None) #advance coroutine
StopIteration: <function check_sanity at 0x105096a60>
# ^ the function is the result of the coroutine
所以只需删除行中的 async
async def decorator(asyncfunc):
你的问题将得到解决:
def ensure_prepare(future):
def decorator(asyncfunc):
@functools.wraps(asyncfunc)
async def wrapper(*args, **kwargs):
future.set_result(await asyncfunc(*args, **kwargs))
return future
return wrapper
return decorator
>>> future = asyncio.Future()
>>> @ensure_prepare(future)
async def check_sanity():
return 9
>>> chech_sanity
<function check_sanity at 0x105784a60>
>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(check_sanity()) #remember to call check_sanity!
<Future finished result=9>
关于python - 使用带修饰协程的单个事件循环返回 future 结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40306458/