requests.get() 默认遇dns失败、连接超时等直接抛出connectionerror或timeout异常导致程序崩溃,因其未被try/except捕获;需将网络异常视为预期分支处理,而非错误,推荐用retry策略实现带退避和上限的自动重试。

为什么 requests.get() 直接报错就崩了?
因为默认情况下 requests.get() 遇到 DNS 失败、连接超时或远程断连,会直接抛出 requests.exceptions.ConnectionError 或 requests.exceptions.Timeout,没捕获就退出。这不是“异常”,是网络常态——你得把它当预期分支来处理,而不是错误。
实操建议:
- 永远用
try/except包住单次请求,至少覆盖requests.exceptions.RequestException(它是所有 requests 异常的父类) - 别只 catch
Timeout:DNS 解析失败(ConnectionError)、SSL 验证失败(SSLError)、空响应(ChunkedEncodingError)都得兜住 - Python 3.12 对 SSL 上下文更严格,某些自签名或过期证书会触发
ssl.SSLCertVerificationError,需显式关闭验证(仅测试环境)或配verify=False
怎么让脚本自动重试又不卡死?
硬写 while True: + time.sleep() 容易失控:无限重试、指数退避没做、没设最大尝试次数。推荐用 urllib3.util.retry.Retry(requests 内置),它和 Python 3.12 兼容且支持状态码重试。
实操建议:
- 构造
Retry实例时,明确指定connect(连接失败)、read(读取超时)、status(如 502/503)三类重试条件 - 用
backoff_factor=1启动指数退避:第 1 次重试等 1s,第 2 次等 2s,第 3 次等 4s……避免雪崩 - 必须设
total=3或类似上限,否则遇到永久性故障(如域名不存在)会一直 retry - 示例:
from requests.adapters import HTTPAdapter<br>from urllib3.util.retry import Retry<br><br>retry_strategy = Retry(<br> total=3,<br> backoff_factor=1,<br> status_forcelist=[429, 502, 503, 504],<br> allowed_methods=["HEAD", "GET", "OPTIONS"]<br>)<br>adapter = HTTPAdapter(max_retries=retry_strategy)
如何判断一次请求“真失败”还是“可恢复”?
HTTP 状态码不是唯一依据。比如返回 200 但 body 是空、JSON 解析失败、字段缺失,这类业务层面失败不会触发 requests 重试机制,但对你的逻辑而言就是失败。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
实操建议:
- 检查
r.status_code之后,立刻验证r.content长度(len(r.content) > 0)和r.headers.get("content-length")是否匹配 - 用
r.json()前先if "application/json" in r.headers.get("content-type", ""),避免非 JSON 响应触发JSONDecodeError - 对关键字段做防御性提取:
data.get("items", [])而不是data["items"],防止 KeyError 中断流程 - 记录原始响应头和前 200 字节 body(
r.content[:200])到日志,方便事后区分是服务端问题还是解析逻辑问题
Python 3.12 的 asyncio + httpx 组合要注意什么?
如果用异步方式并发请求,httpx.AsyncClient 比 requests 更适合,但 Python 3.12 的 asyncio 默认事件循环变更(Windows 上改用 asyncio.WindowsSelectorEventLoopPolicy)可能引发兼容问题。
实操建议:
- 启动前加
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())(仅 Windows),否则可能报RuntimeError: Event loop is closed - 别在
async with httpx.AsyncClient()外调用await client.get(...):client 必须在 async context manager 内使用 - 异步重试不能用
time.sleep(),必须用await asyncio.sleep(1) - 并发数别盲目设高:超过目标服务器承受能力会触发 429,反而降低成功率;建议从
concurrency=5开始压测
真正难的不是加 try 或设 retry,而是分清哪些失败该重试、哪些该跳过、哪些该告警——这得靠你对 API 文档和历史错误日志的观察,不是库能替你决定的。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










