背景

最近在写一些模拟SSO登陆的脚本,由于SSO不是很稳定,总是时不时的超时或者返回5xx错误,但都是偶发性的,如果不进行一定程度的容错处理,那么监控平台将会有太多无效告警,不过在脚本经过Tenacity加持改造的情况下,监控平台的误告大有改善,下面就让我们一起来探索一下这一款近3k Star的Python重试库Tenacity的最佳实践。

过程

本次探索依赖另一个大名鼎鼎的Python库Requests,所以我们先来安装一下依赖和Tenacity库本身。

$ pip3 install requests==2.25.1
$ pip3 install tenacity==7.0.0

下面来看一个小demo,

import requests
from tenacity import *

@retry(reraise=True,stop=stop_after_attempt(2),wait=wait_fixed(2))
def main():
    print("****** Start Try " + str(main.retry.statistics['attempt_number']) + ' ******')
    resp = requests.get('https://httpstat.us/200?sleep=5000', timeout=3)
    print(resp.status_code)

try:
    main()
except requests.exceptions.RequestException as e:
    print(str(e))

其输出如下:

$ python3 demo.py
****** Start Try 1******
****** Start Try 2******
HTTPSConnectionPool(host='httpstat.us', port=443): Read timed out. (read timeout=3)

下面来简单解释一下思路,前面的import就不解释了,这里面的核心就是@retry()这个装饰器了,而这个装饰器的核心又在于reraise=True这个参数,会把异常重新抛出来,上面虽然说是探索,但实际上我直接把最佳实践展示给大家,算是避免大家走弯路了吧。

紧接着第二个stop=stop_after_attempt(2)代表总共执行两次被装饰的函数或方法,然后第三个参数wait=wait_fixed(2)代表中间休息几秒,总共下来一共这3个参数够覆盖大多数场景了,其它更多高级玩法详见这里的Tenacity GitHub Repo, Tenacity的高级玩法真的很多,比如支持异步以及和logging库结合等等。

Tips:

相信细心的你一定注意到了 str(main.retry.statistics[‘attempt_number’]) 这个调用,可以让你知道是第几次在调用函数或方法,很实用哦,赶紧收藏起来小试一下牛刀!