Return 使用带有修饰协程的单个事件循环的未来结果
Return a future result using single event loop with decorated coroutine
我有一个装饰器,它装饰协程函数并将协程 return 编辑的值分配给未来的实例。
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
如您所见,我需要 运行 两次事件循环才能获得未来的结果。有没有办法让事件循环return成为第一个运行之后的值?我不想在我的代码中 await 并将结果(函数)分配给一个名称。
在您的代码中,您已将 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>
我有一个装饰器,它装饰协程函数并将协程 return 编辑的值分配给未来的实例。
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
如您所见,我需要 运行 两次事件循环才能获得未来的结果。有没有办法让事件循环return成为第一个运行之后的值?我不想在我的代码中 await 并将结果(函数)分配给一个名称。
在您的代码中,您已将 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>