Python requests 超时与重试:别让一次网络抖动拖垮脚本
用 Python 写过网络请求的人都遇到过:脚本平时跑得好好的,某天网络抖一下,请求卡住不动,整个任务跟着挂掉。requests 默认是没有超时时间的,timeout 不设,请求可能一直等下去。给每个请求设超时,是写网络代码的第一条规矩。
timeout 参数可以传一个数,也可以传一对数。传一个数是连接超时和读取超时共用同一个值;传元组比如 timeout=(3, 10),前面是连接超时——3 秒连不上就放弃,后面是读取超时——连上了但 10 秒内服务器没返回数据也放弃。区分开的好处是:连接问题通常应该快失败,读取慢则可以多等一会儿。
超时了怎么办,要看场景。查数据的 GET 请求一般可以重试,因为重复查没有副作用;提交订单、扣款这类 POST 请求不能无脑重试——第一次请求可能已经成功了,只是响应丢在半路,重发一次就等于下了两单。重试前先想清楚这个请求是不是幂等的。
重试本身也有讲究。立即重试三次,遇到服务端正好在抖动时等于连敲三下门;更好的做法是指数退避:第一次等 1 秒,第二次等 2 秒,第三次等 4 秒,给服务端喘息的时间。再加上随机抖动,避免成百上千个客户端在同一秒齐刷刷重试,把抖动打成雪崩。requests 自带重试需要配合 urllib3 的 Retry,或者直接用 tenacity 这类库包一层。
最后记住一条排查链路:先看异常类型——ConnectTimeout 是连不上,ReadTimeout 是连上了但回得慢,两种超时指向的问题完全不同;再看是偶发还是持续,偶发加重试,持续先查网络和服务端状态。超时、重试、退避这三件套配齐,脚本才能在真实网络里活下来。
- 点赞
- 收藏
- 关注作者
评论(0)