You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中API请求无限运行时的重试处理问题求助

问题分析与解决方案

你的代码核心问题

  1. 线程目标参数错误:创建Thread时直接调用run_with_timeout(inst_tokens),会导致该函数在主线程立即执行,而非子线程。正确写法应传递函数对象与参数,而非函数调用结果。
  2. 线程无法强制终止:Python线程没有内置强制终止机制,即便thread.join(timeout=10)超时,子线程仍会在后台运行,后续的thread.join()会一直等待线程结束,导致程序无限挂起。

可行解决方案:用进程替代线程

进程拥有独立内存空间,可被强制终止,适合处理这类无法中断的阻塞API调用。以下是两种实现方式:

方案1:使用multiprocessing.Process

import multiprocessing
import time
import datetime

def fetch_quotes(inst_tokens, result_queue):
    try:
        result = client.quotes(instrument_tokens=inst_tokens, quote_type="", isIndex=False)
        result_queue.put(result)
    except Exception as e:
        result_queue.put(e)

retry_delay = 10

while True:
    result_queue = multiprocessing.Queue()
    proc = multiprocessing.Process(target=fetch_quotes, args=(inst_tokens, result_queue))
    proc.start()
    
    # 等待进程结束,超时10秒
    proc.join(timeout=10)
    
    if proc.is_alive():
        # 超时,强制终止进程
        proc.terminate()
        proc.join()  # 确保进程彻底结束
        print(f"Execution of quote API took more than 10 seconds. Retrying in {retry_delay} seconds... {datetime.datetime.now()}")
        time.sleep(retry_delay)
        continue
    
    # 获取结果
    result = result_queue.get()
    if isinstance(result, Exception):
        print(f"API调用出错: {result},重试中... {datetime.datetime.now()}")
        time.sleep(retry_delay)
        continue
    
    # 成功获取数据,退出循环
    break

# 后续处理result

方案2:使用concurrent.futures.ProcessPoolExecutor

该方案更简洁,利用submit和result的超时参数实现控制:

from concurrent.futures import ProcessPoolExecutor, TimeoutError
import time
import datetime

retry_delay = 10

while True:
    with ProcessPoolExecutor(max_workers=1) as executor:
        future = executor.submit(client.quotes, instrument_tokens=inst_tokens, quote_type="", isIndex=False)
        try:
            # 等待结果,超时10秒
            result = future.result(timeout=10)
            break  # 成功获取,退出循环
        except TimeoutError:
            print(f"Execution of quote API took more than 10 seconds. Retrying in {retry_delay} seconds... {datetime.datetime.now()}")
            time.sleep(retry_delay)
        except Exception as e:
            print(f"API调用出错: {e},重试中... {datetime.datetime.now()}")
            time.sleep(retry_delay)

# 后续处理result

为什么线程方案不可行?

Python线程受GIL(全局解释器锁)限制,且无法被强制终止。如果client.quotes是阻塞IO操作,子线程会一直处于阻塞状态,主线程即便判定超时,也无法中断它,最终导致程序挂起。而进程可通过terminate()强制结束,避免资源泄漏与无限等待。

内容的提问来源于stack exchange,提问作者Kuljeet Keshav

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 06:16:25