You need to enable JavaScript to run this app. Python requests.get带stream=True偶发挂起、Ctrl+C中断无效问题排查
优惠活动
大模型
产品
解决方案
定价
更多

Python requests.get带stream=True偶发挂起、Ctrl+C中断无效问题排查

挂起问题的核心诱因

根据提供的完整调用栈可明确,程序阻塞位置并非图片内容下载阶段,而是卡在底层C层面的TLS/SSL握手阻塞调用(栈尾的self._sslobj.do_handshake()),具体诱发因素可拆解为三点:

  • 代码未配置请求超时参数。当前的requests.get(url, stream=True)调用未传入任何timeout配置,requests库默认采用无限等待策略:只要TCP通路建立后,目标服务不返回TLS握手报文、或者中间网络设备(防火墙、代理、NAT网关)直接丢弃数据包不做响应,程序就会永久卡在系统调用层等待,不会主动触发超时退出。
  • Ctrl+C无法即时中断的底层原因。Python的KeyboardInterrupt信号响应依赖解释器在字节码执行间隙检查信号标记,但当代码进入C扩展层的阻塞系统调用(比如SSL握手、socket读操作)时,这个调用会一直等到内核返回结果才会切回Python的执行上下文。此时即便按下Ctrl+C,对应的中断标记也要等阻塞调用自行结束(Windows系统默认的TCP连接超时往往长达数分钟)才会被处理,这就是需要等待极久才能强制终止的根本原因。
  • 偶发触发的场景条件。这类挂起大多出现在遇到半开连接、目标服务握手阶段无响应、代理链路丢包的情况:此时网络路径上既不返回TCP连接重置报文,也不回传握手响应,没有超时兜底的逻辑就会直接卡死流程。
对应修复方案

针对上述问题,仅需要修改代码配置即可彻底解决:

  1. 所有requests请求必须显式配置超时参数,避免无限等待。超时值可以拆分为独立的两部分适配下载场景:
    • 连接超时:从发起请求到完成TCP+TLS握手建链的最长等待时间,通常设置为5-10秒即可覆盖绝大多数正常网络场景
    • 读取超时:建链成功后,两次接收数据块之间的最长等待时间,适配大文件流式下载的需求
      修改后的请求写法参考:
    response = requests.get(
        url,
        stream=True,
        timeout=(10, 30)  # 元组依次对应连接超时、读取超时
    )
    
    配置超时后,即便程序卡在TLS握手阶段,也会在设定的超时阈值到达后主动抛出Timeout异常终止当前阻塞流程,从根本上把最长阻塞时间限制在可接受范围内,同时大幅提升Ctrl+C的中断响应速度。
  2. 可选的稳定性优化:当前代码用for chunk in response遍历响应内容的写法没有固定块大小,可替换为response.iter_content(chunk_size=8192)的方式,在大文件下载场景下稳定性更强。

内容的提问来源于stack exchange,提问作者Tianyu Qi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.30 23:36:07