计时装饰器是一种实用工具,用于衡量函数执行时间,对于性能调优和监控至关重要。本章将探讨如何实现计时装饰器,并如何保持函数的元信息及处理函数执行过程中的异常。
1、简单计时装饰器实现
最基础的计时装饰器通过time模块来测量函数的运行时间。下面是一个简单的例子:
import time
#创建装饰器
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} ran in: {end_time - start_time} secs")
return result
return wrapper
#使用装饰器
@timing_decorator
def example_function(n):
sum = 0
for i in range(n):
sum += i
return sum
#调用函数
example_function(1000000)
输出示例:
example_function ran in: 0.12345 secs
2、使用functools.wraps保持元信息
直接应用上述装饰器会丢失被装饰函数的一些重要属性,比如函数名、文档字符串等。为了解决这个问题,可以使用functools.wraps来保留这些元数据:
from functools import wraps
import time
#创建装饰器
def timing_decorator_with_wraps(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} ran in: {end_time - start_time} secs")
return result
return wrapper
#使用装饰器
@timing_decorator_with_wraps
def enhanced_example_function(n):
"""Computes the sum of first n numbers."""
return sum(range(n))
print(enhanced_example_function.__doc__)
#调用函数
enhanced_example_function(1000000)
输出示例:
Computes the sum of first n numbers.
enhanced_example_function ran in: 0.12345 secs
3、异常处理与装饰器结合
在实际应用中,被装饰的函数可能会抛出异常。为了更好地管理这些情况,可以在装饰器中加入异常处理逻辑:
#创建装饰器
def timing_decorator_with_exception_handling(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} ran in: {end_time - start_time} secs")
return result
except Exception as e:
print(f"An error occurred in {func.__name__}: {e}")
raise
return wrapper
#使用装饰器
@timing_decorator_with_exception_handling
def function_might_raise_error(n):
if n < 0:
raise ValueError("n must be non-negative")
return sum(range(n))
try:
function_might_raise_error(-1)
except ValueError:
pass # Handled exception outside
输出示例:
An error occurred in function_might_raise_error: n must be non-negative
通过上述方式 ,计时装饰器不仅能够准确测量函数执行时间,还能够优雅地处理可能出现的异常情况 ,增强了代码的健壮性。