使用协同程序作为装饰器

时间:2017-02-04 17:19:35

标签: python python-3.x asynchronous

在这种情况下:

async def foo(f):
    async def wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    return wrapper

@foo
async def boo(*args, **kwargs):
    pass

是调用foo作为boo decorator和异步调用的装饰器吗?

- 首先编辑: 另外如何处理调用链的协同作为装饰器?

3 个答案:

答案 0 :(得分:15)

感谢@ blacknght的评论,考虑

def foo():
    def wrapper(func):
        @functools.wraps(func)
        async def wrapped(*args):
             # Some fancy foo stuff
            return await func(*args)
        return wrapped
    return wrapper

def boo():
    def wrapper(func):
        @functools.wraps(func)
        async def wrapped(*args):
            # Some fancy boo stuff
            return await func(*args)
        return wrapped
    return wrapper

作为两个装饰者,

@foo()
@boo()
async def work(*args):
    pass

foo正在包裹work协程时,关键是await两个装饰器中的func(*arg)

答案 1 :(得分:2)

def foo(f):
    async def wrapper(*args, **kwargs):
        return await f(*args, **kwargs)
    return wrapper

@foo
async def boo(*args, **kwargs):
    pass

您的装饰器需要正常运行,然后才能正常工作。

在评估装饰器时,python将以函数为参数执行该方法。

@foo
async def boo():
    pass

评估为:

__main__.boo = foo(boo)

如果foo是一个异步函数,则类型( main .boo)将是协程对象,而不是函数对象。但是,如果foo是常规的synch函数,它将立即求值,而 main .boo将是返回的包装器。

答案 2 :(得分:1)

这是使用decorator库的另一种方法(即首先使用pip install decorator):

import asyncio

import decorator


@decorator.decorator
async def decorate_coro(coro, *args, **kwargs):
    try:
        res = await coro(*args, **kwargs)
    except Exception as e:
        print(e)
    else:
        print(res)


@decorate_coro
async def f():
    return 42


@decorate_coro
async def g():
    return 1 / 0


async def main():
    return await asyncio.gather(f(), g())

if __name__ == '__main__':
    asyncio.run(main())

输出:

42
division by zero