在不稳定或网络依赖的环境中,重试机制是处理临时故障的有效策略。本章将逐步构建重试装饰器 ,从基础到高级,确保操作的成功执行。
6.1 简单重试机制
首先,实现一个基本的重试逻辑,当函数执行失败时自动重试固定次数。
def retry_on_failure(retries=3):
def decorator(func):
def wrapper(*args, **kwargs):
attempt = 0
while attempt <= retries:
try:
return func(*args, **kwargs)
except Exception:
attempt += 1
if attempt > retries:
raise
return wrapper
return decorator
@retry_on_failure()
def might_fail_randomly():
import random
if random.randint(0, 9) > 5: # 模拟随机失败
raise Exception("Temporary failure.")
return "Success!"
print(might_fail_randomly())
此装饰器在函数失败时尝试重新执行,直到达到设定的重试次数。
6.2 配置重试次数与间隔
为了更精细的控制,我们可以让装饰器支持自定义重试次数和每次重试间的延迟。
import time
def retry_with_delay(retries=3, delay=1):
def decorator(func):
def wrapper(*args, **kwargs):
attempt = 0
while attempt <= retries:
try:
return func(*args, **kwargs)
except Exception:
attempt += 1
if attempt <= retries:
time.sleep(delay)
else:
raise
return wrapper
return decorator
@retry_with_delay(retries=5, delay=2)
def simulate_network_issue():
import random
if random.randint(0, 9) > 7: # 模拟网络不稳定
raise IOError("Network issue.")
return "Data fetched."
print(simulate_network_issue())
现在,每次重试之间会有固定的延迟 ,有助于缓解瞬时资源压力。
6.3 智能重试(根据异常类型)
在某些情况下,只应对特定类型的异常进行重试是有意义的。我们可以通过判断捕获的异常类型来实现智能重试。
def retry_on_specific_errors(retries=3, delay=1, error_types=(Exception,)):
def decorator(func):
def wrapper(*args, **kwargs):
attempt = 0
while attempt <= retries:
try:
return func(*args, **kwargs)
except tuple(error_types) as e:
attempt += 1
if attempt <= retries:
time.sleep(delay)
print(f"Retrying due to {e.__class__.__name__}.")
else:
raise
return wrapper
return decorator
@retry_on_specific_errors(retries=3, error_types=(ConnectionError,))
def fetch_remote_data(url):
# 这里假设了fetch_data函数会抛出ConnectionError
raise ConnectionError("Failed to connect.")
try:
fetch_remote_data("http://example.com/data")
except Exception as e:
print(f"Failed after retries: {e}")
通过指定重试应针对的异常类型列表 ,装饰器变得更加智能,仅对预期的暂时性错误进行重试。
这些重试装饰器的实现展示了如何在Python中灵活地处理函数调用失败,通过自动化重试机制提升系统的稳定性和健壮性。