从Postman API获取大集合时遇IncompleteRead错误求解决方案
稳定获取Postman API大型集合的解决方案
1. 针对性优化重试策略
普通重试可能没覆盖到IncompleteRead和ChunkedEncodingError这类异常,得把这些异常加入重试触发规则,同时用指数退避避免频繁请求Postman服务器:
from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import requests from urllib3.exceptions import IncompleteRead from requests.exceptions import ChunkedEncodingError def get_retry_session(): session = requests.Session() retry_strategy = Retry( total=5, # 最多重试5次 backoff_factor=1, # 重试间隔按1s、2s、4s递增 status_forcelist=[429, 500, 502, 503, 504], # 这些HTTP状态码自动重试 allowed_methods=["GET"], # 只对GET请求重试(避免修改类请求重复执行) retry_on_exception=lambda exc: isinstance(exc, ( ConnectionError, TimeoutError, IncompleteRead, ChunkedEncodingError )) ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("https://", adapter) session.mount("http://", adapter) session.timeout = (10, 120) # 连接超时10s,读取超时120s(大文件可按需延长) return session
2. 流式读取响应,避免一次性加载
大集合内容直接一次性读取容易触发连接中断,改用逐块流式读取,降低内存占用同时减少连接压力:
def fetch_large_collection(session, api_url): try: with session.get(api_url, stream=True) as resp: resp.raise_for_status() chunk_size = 1024 * 1024 # 每次读1MB full_content = b"" for chunk in resp.iter_content(chunk_size=chunk_size): if chunk: full_content += chunk return full_content.decode("utf-8") except Exception as e: raise RuntimeError(f"获取集合失败: {str(e)}")
3. 调整urllib3连接池配置(极端场景)
连接池复用可能导致旧连接失效,试试禁用连接池复用或者强制清空连接池:
在创建session时添加:
# 清空连接池 session.adapters["https://"].poolmanager.clear() # 或者限制连接池大小,避免复用旧连接 retry_strategy.pool_connections = 1 retry_strategy.pool_maxsize = 1
4. Postman API专属优化
- 拆分请求:如果Postman API支持分页,把大集合拆成多个小请求分批获取,再合并结果,降低单次请求的压力。
- 关闭响应压缩:有时候压缩传输会导致解析异常,试试在请求头里禁用压缩(会增加传输量,按需使用):
headers = {"Accept-Encoding": "identity"} resp = session.get(api_url, headers=headers, stream=True)
5. 断点续传兜底
如果还是偶尔失败,实现断点续传,记录已读取的字节数,下次请求时从断点继续获取:
def resume_fetch(session, api_url, saved_content=b""): headers = {} if saved_content: headers["Range"] = f"bytes={len(saved_content)}-" try: with session.get(api_url, headers=headers, stream=True) as resp: resp.raise_for_status() if resp.status_code == 206: # 服务器支持断点续传 chunk_size = 1024 * 1024 for chunk in resp.iter_content(chunk_size=chunk_size): if chunk: saved_content += chunk return saved_content elif resp.status_code == 200: # 首次获取或服务器不支持断点,重新读全量 return fetch_large_collection(session, api_url) except Exception as e: # 保存已读取的内容,下次可继续 with open("partial_collection.bin", "wb") as f: f.write(saved_content) raise RuntimeError(f"请求中断,已保存部分内容: {str(e)}")
内容的提问来源于stack exchange,提问作者Alvaro
相关产品推荐
相关产品推荐

