python - 使用带修饰协程的单个事件循环返回 future 结果

标签 python python-3.5 python-asyncio

我有一个装饰器,它装饰协程函数并将协程返回的值分配给 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/

相关文章:

python - Pandas:如何按 groupby 值求和

python - 如何模拟 Django 模型对象(及其方法)?

python-3.x - 如何使用FastApi和SqlAlchemy进行异步操作

python - Pycrypto 安装 fatal error : gmp. h 文件未找到

python - 可以在集合中使用插入符和前瞻吗?

python - 精度损失 numpy - mpmath

json - TypeError : <botocore. response.StreamingBody object at 0x7f81898af438> is not JSON serializable

python - 限制尝试读取文件仅几次

python - 在 on_ready 中发送消息? Python不和谐机器人

python - 测试和模拟使用 async with 语句的异步代码