关键词:重试 | 异常处理 | 递归 | 装饰器
有些程序的运行需要依赖多变而不可控的外部环境,比如网络爬虫。在程序中我们很难将所有外部引入的异常都考虑到,特别是那些时有时无的异常,这时如果程序有自动重试的机制,无疑可以省不少事。
本文实现的重试机制在遇到异常时会记录遇到异常后重试的次数,如果次数小于允许的重试次数,则进行下一次重试,否则将异常上抛。下面第一部分是函数实现,第二部分在前者基础上略作改动,变成了更灵活的装饰器实现。实现只涉及异常处理、递归、装饰器的知识,示例也足够明晰,因此不多费口舌。
函数实现
import sys, os
import time, random
MAXIMAL_RETRY = 3
# Function Method
def run():
result = random.random() # generate random double from 0 to 1
if result > 0.3:
raise Exception(f'Wrong result: {result}')
else:
print(f'>> Success')
return result
def run_with_retry(times=0):
time.sleep(1)
try:
return run()
except Exception as e:
if times >= MAXIMAL_RETRY:
print(f'>> Exceed maximal retry {MAXIMAL_RETRY}, Raise exception...')
raise(e) # will stop the program without further handling
else:
times += 1
print(f'>> Exception, Retry {times} begins...')
return run_with_retry(times)
def test_retry_func():
while True:
print('\nBegin new run...')
time.sleep(1)
result = run_with_retry()
if result:
print(f'Get result: {result}')
if __name__ == "__main__":
test_retry_func()
装饰器实现
import sys, os
import time, random
MAXIMAL_RETRY = 3
def retry(func, times=0):
def retried(*args, **kwargs):
nonlocal times
time.sleep(1)
try:
return run()
except Exception as e:
if times >= MAXIMAL_RETRY:
print(f'>> Exceed maximal retry {MAXIMAL_RETRY}, Raise exception...')
raise(e) # will stop the program without further handling
else:
times += 1
print(f'>> Exception, Retry {times} begins...')
return run_with_retry(times)
return retried
@retry
def run_decorated():
result = random.random() # generate random double from 0 to 1
if result > 0.3:
raise Exception(f'Wrong result: {result}')
else:
print(f'>> Success')
return result
def test_retry_decorator():
while True:
print('\nBegin new run...')
time.sleep(1)
result = run_decorated()
if result:
print(f'Get result: {result}')
if __name__ == "__main__":
test_retry_decorator()
注:关键字nonlocal
的作用是让函数retried
的变量名times
绑定到外部函数retry
的参数times
,相当于引用传值。更详细说明可见Python官方文档。
经过上一篇《数据热更新》的折磨这篇来个简单的(这句话用于凑够简书已公开文章10万总字数XD)
网友评论