写了一个装饰器函数,可以在函数运行发生错误的时候自动发起重试,适合爬虫场景
# -*- coding: utf-8 -*-
from functools import wraps
from typing import Tuple
import time
import random
import sys
def retry(exception_tuple: Tuple[Exception], maxretries: int, time_interval: float):
'''
Args:
exception_tuple: 由Exception类组成的元组。函数只会在发生指定的错误时重试
maxretries: 最大重试次数
time_interval: 重试的间隔时间
'''
def decorator(func):
retry_count = 0
@wraps(func)
def wrapper(*args, **kwargs):
result = None
nonlocal retry_count
try:
result = func(*args, **kwargs)
except exception_tuple as err:
if retry_count <= maxretries:
retry_count += 1
time.sleep(time_interval)
print(f'! 发生错误: {err}, 即将进行第{retry_count}次尝试')
result = wrapper(*args, **kwargs)
else:
print(f'! {err}: 在{maxretries}次尝试后依然失败.')
sys.exit(0)
except Exception as err:
print(f'! 发生未预料的错误: {err}')
raise err
else:
retry_count = 0 # 成功执行一次后清除retry的记录
return result
return wrapper
return decorator
if __name__ == "__main__":
@retry(exception_tuple=(ValueError, TypeError, IndexError),
maxretries=5,
time_interval=3)
def crash_randomly():
code = random.choices([0, 1, 2, 3], weights=[0.7, 0.1, 0.1, 0.1], k=1).pop()
if code == 1:
raise ValueError("Error Type 1")
elif code == 2:
raise TypeError("Error Type 2")
elif code == 3:
raise IndexError("Error Type 3")
elif code == 0:
print("程序幸运地度过了一劫")
while True:
crash_randomly()