以下是一个能够记录同步和异步函数执行时间的装饰器实现:
import time
import functools
from inspect import iscoroutinefunction
def record_time(func):
"""记录函数执行时间的装饰器,支持同步和异步函数"""
# 处理同步函数
@functools.wraps(func)
def sync_wrapper(*args, **kwargs):
start_time = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start_time
print(f"[同步] 函数 {func.__name__} 执行时间: {elapsed:.4f}秒")
return result
# 处理异步函数
@functools.wraps(func)
async def async_wrapper(*args, **kwargs):
start_time = time.perf_counter()
result = await func(*args, **kwargs)
elapsed = time.perf_counter() - start_time
print(f"[异步] 函数 {func.__name__} 执行时间: {elapsed:.4f}秒")
return result
# 根据函数类型返回对应的包装器
return async_wrapper if iscoroutinefunction(func) else sync_wrapper
使用示例:
# 测试同步函数
@record_time
def sync_task():
time.sleep(1)
return "同步任务完成"
# 测试异步函数
@record_time
async def async_task():
await asyncio.sleep(1)
return "异步任务完成"
# 运行测试
if __name__ == "__main__":
# 测试同步函数
print(sync_task())
# 测试异步函数
import asyncio
print(asyncio.run(async_task()))
实现说明:
- 使用
time.perf_counter()
获取高精度时间戳,比time.time()
更适合性能测量 - 通过
inspect.iscoroutinefunction
判断被装饰函数是否是异步函数 - 使用
functools.wraps
保留原始函数的元信息 - 同步版本直接执行函数并计算耗时
- 异步版本使用
await
执行并计算耗时 - 输出信息中标注了函数类型便于区分
输出示例:
[同步] 函数 sync_task 执行时间: 1.0012秒
同步任务完成
[异步] 函数 async_task 执行时间: 1.0015秒
异步任务完成
该装饰器特点:
- 自动识别同步/异步函数
- 保持函数返回值不变
- 使用高精度计时器
- 保留原始函数元信息
- 输出信息包含函数类型标识
- 同时支持带参数和不带参数的函数
- 兼容各种Python 3.5+的协程语法