Ответ
Чтобы создать декоратор для асинхронной (async def) функции, его внутренняя функция-обертка (wrapper) также должна быть асинхронной и использовать await для вызова декорируемой функции.
Важно использовать @functools.wraps для сохранения метаданных исходной функции (имени, документации), что упрощает отладку.
Основной шаблон:
import asyncio
import functools
import time
def async_timer_decorator(func):
"""Декоратор для измерения времени выполнения асинхронной функции."""
@functools.wraps(func)
async def wrapper(*args, **kwargs):
# Обертка должна быть async def
print(f"Вызов функции {func.__name__}...")
start_time = time.time()
# Вызов оригинальной функции через await
result = await func(*args, **kwargs)
end_time = time.time()
print(f"Функция {func.__name__} выполнилась за {end_time - start_time:.4f} секунд")
return result
return wrapper
@async_timer_decorator
async def some_async_task():
print("Выполняется асинхронная задача...")
await asyncio.sleep(1)
return "Задача завершена"
Ключевые принципы:
- Асинхронная обертка: Внутренняя функция
wrapperобъявляется сasync def. - Использование
await: Оригинальная функция вызывается с помощьюawait func(...). - Сохранение метаданных: Декоратор
@functools.wraps(func)применяется кwrapperдля корректного наследования атрибутов (__name__,__doc__и т.д.).
Пример использования:
async def main():
result = await some_async_task()
print(result)
# Запуск в асинхронном контексте
asyncio.run(main())
# Вывод:
# Вызов функции some_async_task...
# Выполняется асинхронная задача...
# Функция some_async_task выполнилась за 1.0012 секунд
# Задача завершена