transform a "normal" decorator in one for async functions

vito.detullio at gmail.com vito.detullio at gmail.com
Tue Sep 18 10:20:06 EDT 2018


Hi.

Let's say I have this library that expose a decorator; it's meant to be used with normal functions.

but I have to "apply" the decorator to an async function.
>From what I understand I cannot "really" wait for this decorated async function, as it's not really "async", and, from a simple test I made, I see that the order of execution is not really "straight" (I have simplifield the example to the bone)

    import asyncio

    def deco(fun): # the "classic" decorator
        def wrap(*args, **kwargs):
            print('wrap begin')
            try:
                return fun(*args, **kwargs)
            finally:
                print('wrap end')
        return wrap

    @deco
    async def decorated_async():
        print('a')
        await asyncio.sleep(1)
        print('b')
    
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(decorated_async())
    loop.close()

the output of this script is

    wrap begin
    wrap end
    a
    b

while an "async-aware" decorator (with an "async" wrap that "await"s the fun call) would print the "wrap end" line at the end.

I can easily rewrite my dumb decorator to handle async functions (I can just make an "async def wrap" and "return await fun"), but I cannot rewrite this library.

is there a way to "convert" a "normal" decorator in one that can handle async functions?

Thanks



More information about the Python-list mailing list