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

Python调用API超时问题:如何修改批量请求代码避免超时?

解决API调用超时问题的优化方案

针对批量调用API超时的问题,可以从以下几个方向修改代码:

1. 添加超时重试机制

单次超时可能是临时网络波动或服务器负载波动,添加重试逻辑可自动重试失败请求,避免直接放弃。可以用第三方库实现,也可手动编写:

手动实现重试逻辑

def get_val(element):
    url = 'https://www.xxxx/yyy/api/search'
    headers = {'Content-Type': 'application/json'}
    param = {'q': element, 'page' : 500}
    max_retries = 3
    retry_count = 0
    
    while retry_count < max_retries:
        try:
            response = requests.get(url, headers=headers, params=param, timeout=(3.05, 27))
            response.raise_for_status()  # 触发HTTP状态码异常
            docs = response.json()['response']['docs']
            
            for result in docs:
                file.write("%s\t%s\n" % (element, result['short_form']))
            return  # 请求成功则退出循环
        except Timeout:
            retry_count += 1
            print(f'元素 {element} 超时,正在重试 {retry_count}/{max_retries}')
        except Exception as e:
            print(f'元素 {element} 处理出错: {str(e)}')
            break  # 非超时异常直接终止重试
    print(f'元素 {element} 经过 {max_retries} 次重试仍失败')

使用tenacity库简化重试

from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from requests.exceptions import Timeout

@retry(stop=stop_after_attempt(3), 
       wait=wait_exponential(multiplier=1, min=2, max=10), 
       retry=retry_if_exception_type(Timeout))
def get_val(element):
    url = 'https://www.xxxx/yyy/api/search'
    headers = {'Content-Type': 'application/json'}
    param = {'q': element, 'page' : 500}
    
    response = requests.get(url, headers=headers, params=param, timeout=(3.05, 27))
    response.raise_for_status()
    docs = response.json()['response']['docs']
    
    for result in docs:
        file.write("%s\t%s\n" % (element, result['short_form']))

2. 控制请求频率

连续高频请求容易触发服务器限流,导致超时或被封禁,可在每次请求后添加短暂延迟:

import time

# 循环调用时添加延迟
for i in lst:
    for element in i:
        get_val(element)
        time.sleep(0.5)  # 每次请求后暂停0.5秒,可根据实际情况调整时长

3. 复用HTTP连接

显式配置连接池,减少重复建立连接的开销,提升请求效率:

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

# 创建会话并配置连接池与重试策略
session = requests.Session()
retry_strategy = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[429, 500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount('https://', adapter)

# 修改get_val函数使用会话
def get_val(element, session):
    url = 'https://www.xxxx/yyy/api/search'
    headers = {'Content-Type': 'application/json'}
    param = {'q': element, 'page' : 500}
    
    try:
        response = session.get(url, headers=headers, params=param, timeout=(3.05, 27))
        response.raise_for_status()
        docs = response.json()['response']['docs']
        
        for result in docs:
            file.write("%s\t%s\n" % (element, result['short_form']))
    except Timeout:
        print(f'元素 {element} 请求超时')

# 循环调用时传入会话
for i in lst:
    for element in i:
        get_val(element, session)
        time.sleep(0.5)

4. 改用异步请求提升效率

同步串行请求效率低,使用aiohttp实现异步请求,同时控制并发数,既提升速度又避免压垮服务器:

import asyncio
import aiohttp
import aiofiles

async def get_val_async(element, session, semaphore, file):
    url = 'https://www.xxxx/yyy/api/search'
    headers = {'Content-Type': 'application/json'}
    param = {'q': element, 'page' : 500}
    max_retries = 3
    retry_count = 0
    
    async with semaphore:
        while retry_count < max_retries:
            try:
                async with session.get(url, headers=headers, params=param, timeout=aiohttp.ClientTimeout(total=27, connect=3.05)) as response:
                    response.raise_for_status()
                    docs = await response.json()
                    docs = docs['response']['docs']
                    
                    for result in docs:
                        await file.write(f"{element}\t{result['short_form']}\n")
                return
            except asyncio.TimeoutError:
                retry_count += 1
                print(f'元素 {element} 超时,正在重试 {retry_count}/{max_retries}')
            except Exception as e:
                print(f'元素 {element} 处理出错: {str(e)}')
                break
        print(f'元素 {element} 经过 {max_retries} 次重试仍失败')

async def main(lst, output_path):
    # 控制最大并发数,比如同时最多10个请求
    semaphore = asyncio.Semaphore(10)
    async with aiohttp.ClientSession() as session:
        async with aiofiles.open(output_path, 'a', encoding='utf-8') as file:
            tasks = []
            for sub_list in lst:
                for element in sub_list:
                    task = asyncio.create_task(get_val_async(element, session, semaphore, file))
                    tasks.append(task)
            await asyncio.gather(*tasks)

# 运行异步主函数
asyncio.run(main(lst, 'output.txt'))

5. 记录失败请求

建议记录处理失败的元素,后续可单独重试,避免数据丢失:

failed_elements = []

# 在get_val的异常处理中添加记录
except Timeout:
    failed_elements.append(element)
    print(f'元素 {element} 请求超时')

# 循环结束后保存失败列表
with open('failed_elements.txt', 'w', encoding='utf-8') as f:
    for elem in failed_elements:
        f.write(f"{elem}\n")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:30:58