Async decorators with parameters in Python
I had a hard time find a decorator example that used async and had some parameters, so I wrote this blog post.
I think the confusing things were:
-
The function your wrapping should be async and you need to await it within the decorator.
-
The outer wrapper uses the params and returns the inner wrapper. The inner wrapper then consumes the function that is wrapped. This feels the same as currying in functional methods.
import asyncio
import sys
import uvloop
from functools import wraps
def do_n_times(n=2):
# this returns a function that _actually_ gets passed the wrapped method.
def wrapper(func):
@wraps(func)
async def wrapper_do_n_times():
for _ in range(n-1):
await func()
return await func()
return wrapper_do_n_times
return wrapper
@do_n_times(n=4)
async def print_me():
print("me")
pass
if sys.version_info >= (3, 11):
with asyncio.Runner(loop_factory=uvloop.new_event_loop) as runner:
runner.run(print_me())
else:
uvloop.install()
asyncio.run(print_me())