Python 网络请求总超时?四个让脚本更稳健的小习惯
【摘要】 网络请求偶发超时、返回 502 并不少见。本文分享四个小习惯:显式设置超时、只对值得重试的失败重试、复用 Session、把失败写进日志,让 Python 脚本跑得更稳。
写定时任务、批量下载文件时,网络请求最常见的毛病不是报错,而是“偶尔”失败:白天好好的,半夜跑批就超时;换个网络环境就返回 502。请求本身没写错,缺的是几层兜底。下面四个习惯,都是小改动,收益很实在。
一、永远显式设置 timeout
requests.get(url) 不传 timeout 时,默认会一直等下去,一个挂起的连接就能拖垮整个任务。建议写成连接超时和读取超时分开的元组:
import requests
resp = requests.get(url, timeout=(3, 10))
3 是建立连接的最长等待秒数,10 是服务器返回数据的最长等待秒数。数值按接口情况调整,但一定不要留空。
二、只对“值得重试”的失败重试
不是所有失败都该重试。连接超时、429、5xx 这类临时性问题值得再试一次;400、401、404 这类请求本身有问题的,重试多少次结果都一样。加一个带上限和退避的循环:
import time
import requests
def fetch(url, retries=3):
for attempt in range(retries):
try:
resp = requests.get(url, timeout=(3, 10))
if resp.status_code in (429, 500, 502, 503, 504):
raise requests.HTTPError(resp.status_code)
return resp
except (requests.Timeout, requests.ConnectionError, requests.HTTPError) as e:
if attempt == retries - 1:
raise
time.sleep(2 ** attempt)
等待时间按 1 秒、2 秒、4 秒递增,避免在服务端刚恢复时又被瞬时流量打垮。
三、复用 Session,别每次都新建连接
循环里反复调用 requests.get 会每次重新建连、重新握手。改成一个 Session 复用连接,还能顺手统一请求头:
session = requests.Session()
session.headers.update({"User-Agent": "my-script/1.0"})
resp = session.get(url, timeout=(3, 10))
四、把失败写进日志,而不是只打印出来
线上跑的脚本,print 的输出常常没人看。把每次重试、最终失败和耗时记下来,出问题时才有据可查:
import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logging.warning("第 %d 次请求失败,%s 秒后重试", attempt + 1, 2 ** attempt)
小结
四个习惯一句话概括:设超时、防死等;重试要分情况、要有上限和退避;复用连接;失败留痕。把它们写进你下一个脚本的模板里,半夜的告警会少很多。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)