当前位置:首页 > 文章列表 > 文章 > python教程 > Python requests 请求一直卡住怎么办:timeout、状态码和重试一步步排查

Python requests 请求一直卡住怎么办:timeout、状态码和重试一步步排查

来源:17golang原创 2026-06-16 16:17:22 0浏览 收藏

用 Python 写接口调用时,最怕的一类问题不是立刻报错,而是程序一直停在那里。日志没有继续输出,任务队列越堆越多,手动中断后才发现卡在 requests.get() 这一行。

我们这次按排查路线来走:先复现没有 timeout 的卡住现象,再加上超时限制,接着检查 HTTP 状态码,最后给临时失败场景加上有限重试。这样处理后,请求失败会变成可控失败,而不是把整个任务拖住。

摘要

requests 默认不会自动给请求设置超时时间。调用外部接口时,建议显式传入 timeout,再用 raise_for_status() 检查状态码。对 429、500、502、503、504 这类可重试状态,可以用 HTTPAdapterRetry 做有限重试,最后再检查返回体是否能按预期解析。

适合人群

  • 使用 Python requests 调第三方接口、内部接口或爬取公开页面的开发者。
  • 遇到接口调用偶发卡住、任务队列堆积、日志停在请求阶段的后端同学。
  • 想把 timeout、状态码检查和重试封装成统一请求方法的项目维护者。
目录
  • 问题现场:请求没有 timeout 导致任务卡住
  • 第一步验证:给请求加上 timeout
  • 第二步定位:状态码不能只看有没有返回
  • 修复方案:timeout、状态码检查和 Retry 组合
  • 最终封装:一个可复用的请求函数
  • 常见坑位
  • 总结检查清单

问题现场:请求没有 timeout 导致任务卡住

我们先看现象。一个同步任务每天拉取外部接口数据,平时几秒钟就能结束。有一天任务突然没有结束,日志最后一行停在“开始请求外部 API”,后续解析、入库、完成日志都没有出现。

import requests

def fetch_user_profile(user_id):
    url = f"https://api.example.test/users/{user_id}"
    response = requests.get(url)
    return response.json()

这段代码看起来很普通,但问题在于它没有设置 timeout。当网络链路、目标服务或代理层长时间没有返回时,任务可能一直等待。队列型任务里这会直接带来连锁反应:一个 worker 卡住,后面的任务开始堆积。

Python requests 没有 timeout 时任务等待、任务堆积,设置 timeout 后快速失败并进入重试恢复

这一步说明,我们不能只关注“接口是否能通”,还要给每次调用设定等待上限。超时不是坏事,它是把不可控等待变成可控失败的第一道边界。

第一步验证:给请求加上 timeout

接着验证这个猜测。我们先不改复杂结构,只给请求加一个明确的超时时间。requeststimeout 可以传一个数字,也可以传一个二元组,分别表示连接超时和读取超时。

import requests

def fetch_user_profile(user_id):
    url = f"https://api.example.test/users/{user_id}"
    response = requests.get(url, timeout=(3, 10))
    return response.json()

这里的 (3, 10) 表示连接阶段最多等 3 秒,服务已连接后读取响应最多等 10 秒。实际项目里要根据接口特征调整:内网接口通常更短,跨网络或第三方接口可以略长,但不建议完全不设。

加上 timeout 后,程序不会无限等待。它会在超时后抛出错误,我们就可以在外层捕获并记录上下文。

try:
    data = fetch_user_profile(1001)
except requests.exceptions.Timeout:
    print("请求超时,稍后重试或进入失败分支")

第二步定位:状态码不能只看有没有返回

现在请求不会无限卡住了,但还有一个隐藏问题:接口返回了,不代表业务成功。比如 500、502、503、504 都可能有响应体;如果代码直接 response.json(),可能把失败响应当成正常数据继续处理。

所以第二步要检查状态码。最直接的方式是调用 raise_for_status(),让非 2xx/3xx 的响应进入错误分支。

import requests

def fetch_user_profile(user_id):
    url = f"https://api.example.test/users/{user_id}"
    response = requests.get(url, timeout=(3, 10))
    response.raise_for_status()
    return response.json()

这一步的意义是把“有响应”拆成两层判断:先确认 HTTP 层成功,再解析业务数据。否则日志里只看到“请求完成”,但数据结构可能已经错了。

修复方案:timeout、状态码检查和 Retry 组合

现在可以定位到完整原因:没有超时会导致任务长期等待;没有状态码检查会让失败响应混进正常流程;没有有限重试会让临时抖动直接变成失败。解决方案是把这三件事组合起来。

Python requests 使用 Session、timeout、状态码检查、Retry、JSON 检查并返回可控结果

对临时故障,可以使用 urllib3Retry 配合 requests.adapters.HTTPAdapter。下面示例只对 GET 和 HEAD 这类适合重试的请求启用策略,并限制重试次数。

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

def build_session():
    retry = Retry(
        total=2,
        connect=2,
        read=2,
        status=2,
        backoff_factor=0.5,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods={"GET", "HEAD"},
        raise_on_status=False,
    )

    adapter = HTTPAdapter(max_retries=retry)
    session = requests.Session()
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    return session

这里不要把重试次数设得太大。重试是用来抵抗临时抖动,不是用来掩盖接口长期不可用。对写操作尤其要谨慎,除非接口本身有幂等设计,否则不要轻易自动重试。

最终封装:一个可复用的请求函数

最后把请求逻辑封装起来。我们希望得到的不是“永远成功”,而是失败时能清楚返回是哪一类失败:超时、HTTP 状态异常、JSON 解析失败,还是其他请求错误。

import requests

session = build_session()

def get_json(url, params=None):
    try:
        response = session.get(url, params=params, timeout=(3, 10))
        response.raise_for_status()
        return {
            "ok": True,
            "data": response.json(),
            "status_code": response.status_code,
        }
    except requests.exceptions.Timeout as error:
        return {"ok": False, "type": "timeout", "message": str(error)}
    except requests.exceptions.HTTPError as error:
        status_code = error.response.status_code if error.response else None
        return {"ok": False, "type": "http", "status_code": status_code}
    except requests.exceptions.JSONDecodeError as error:
        return {"ok": False, "type": "json", "message": str(error)}
    except requests.exceptions.RequestException as error:
        return {"ok": False, "type": "request", "message": str(error)}

这样封装后,上层业务就不用猜失败原因。比如 typetimeout,可以进入稍后重试;typehttp,可以看状态码决定是否告警;typejson,说明接口返回体不是预期格式。

常见坑位

1. 只设置连接超时,不设置读取超时

如果只传一个数字,写法简单,但不容易区分连接阶段和读取阶段。对接口排查来说,二元组更清楚:连接慢和响应慢是两类问题。

2. 所有方法都自动重试

GET 请求通常更适合重试,POST、PATCH、DELETE 等写操作要看接口是否支持幂等。如果没有幂等保障,自动重试可能造成重复提交。

3. 没有记录上下文

捕获错误后只打印“请求失败”不够。至少要记录 URL、参数摘要、状态码、失败类型和耗时。这样后续才能判断是网络问题、服务问题,还是数据格式问题。

4. 把 Retry 当成稳定性保证

Retry 只是缓冲短暂抖动。如果接口长期慢或频繁 5xx,真正要做的是限流、降级、熔断或联系接口提供方,而不是无限增加重试次数。

总结检查清单

  • 每个外部 HTTP 调用都要显式设置 timeout
  • 先检查 response.raise_for_status(),再解析 JSON。
  • 只对适合重试的方法和状态码启用有限 Retry。
  • 错误返回要区分 timeouthttpjsonrequest
  • 日志要包含失败类型、状态码和关键业务参数摘要。

回到最开始的问题:requests 请求一直卡住,第一反应应该是检查有没有设置 timeout。把超时、状态码检查、有限重试和返回体检查连成固定流程,接口调用才会从“偶发卡死”变成“失败可控、原因可查”。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
PHP PDO 事务完整工作流:开启事务、提交、回滚和异常模式PHP PDO 事务完整工作流:开启事务、提交、回滚和异常模式
上一篇
PHP PDO 事务完整工作流:开启事务、提交、回滚和异常模式
Linux 磁盘 IO 飙高怎么办:从 iostat 到 pidstat 一步步定位
下一篇
Linux 磁盘 IO 飙高怎么办:从 iostat 到 pidstat 一步步定位
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ljg-skills -
    ljg-skills
    ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
    64次使用
  • MELO音乐 - AI 音乐生成平台,支持多模态创作能力
    MELO音乐
    MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
    76次使用
  • UniScribe - AI 免费在线音视频转文字平台
    UniScribe
    UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
    77次使用
  • 剧云 - 免费 AI 智能中文剧本创作平台
    剧云
    剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
    222次使用
  • 万象有声 - AI 一站式有声内容创作平台
    万象有声
    万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
    221次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码