На этапе декорирования проверьте inspect.iscoroutinefunction и создайте async-обёртку для async def, обычную — для def. Обе должны сохранять аргументы, результат и исключения.
Как сделать декоратор, который работает и с синхронными, и с асинхронными функциями?
На этапе декорирования проверьте inspect.iscoroutinefunction и создайте async-обёртку для async def, обычную — для def. Обе должны сохранять аргументы, результат и исключения.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
На этапе декорирования проверьте inspect.iscoroutinefunction и создайте async-обёртку для async def, обычную — для def. Обе должны сохранять аргументы, результат и исключения.
import inspect
from functools import wraps
def traced(func):
if inspect.iscoroutinefunction(func):
@wraps(func)
async def async_wrapper(*args, **kwargs):
return await func(*args, **kwargs)
return async_wrapper
@wraps(func)
def sync_wrapper(*args, **kwargs):
return func(*args, **kwargs)
return sync_wrapper
В соответствующую обёртку добавляют логирование или замер времени. Проверка покрывает обычные функции def и async def, но не все произвольные callable-объекты и синхронные фабрики awaitable. Для них нужно явно определить контракт. Нельзя вызывать asyncio.run внутри уже работающего event loop ради унификации.