并发超时错误下如何获取已完成的HTTP请求部分结果?
如何在全局超时的并行请求中获取已完成的结果
当你使用Executor.map()并设置全局超时的时候,一旦超时触发,map会直接抛出TimeoutError,此时还没来得及生成完整的结果列表,自然拿不到已经完成的任务结果。这是因为map的设计是等待所有任务完成后一次性返回结果,中途超时就会中断整个流程。
要解决这个问题,你需要换一种方式提交和跟踪任务:放弃map,改用submit逐个提交任务,配合as_completed实时收集已完成的结果,同时控制总超时时间。
具体实现代码
import concurrent.futures from concurrent.futures import ThreadPoolExecutor, TimeoutError, as_completed def get_partial_results(urls, tecton_timeout): # 用字典保存每个URL对应的结果(或异常信息) url_to_result = {} with ThreadPoolExecutor() as executor: # 逐个提交任务,建立Future对象与URL的映射 future_to_url = {executor.submit(self._fetch_feature, url): url for url in urls} try: # 遍历所有已完成的任务,设置全局超时 for future in as_completed(future_to_url, timeout=tecton_timeout): url = future_to_url[future] try: # 获取单个任务的结果 result = future.result() url_to_result[url] = result except Exception as task_err: # 处理单个请求自身的异常(比如HTTP请求失败) url_to_result[url] = f"Request failed: {str(task_err)}" except TimeoutError: # 全局超时触发,处理未完成的任务 for future in future_to_url: if not future.done(): # 取消未完成的任务,避免资源浪费 future.cancel() url_to_result[future_to_url[future]] = "Task timed out" # 按原URL顺序整理结果(可选,根据需求调整) ordered_results = [url_to_result.get(url, "No result") for url in urls] return ordered_results
关键说明
- 任务提交与映射:用
executor.submit()逐个提交请求,通过future_to_url字典把每个Future对象和对应的URL绑定,方便后续把结果和请求对应起来。 - 实时收集结果:
as_completed()会在任务完成时立即返回对应的Future,这样可以在超时前尽可能多地收集已完成的结果。 - 异常区分处理:外层的
try-except捕获全局超时,内层的try-except处理单个请求自身的异常(比如网络错误),避免单个请求失败导致整个流程中断。 - 资源清理:超时触发后,调用
future.cancel()取消未完成的任务,释放线程资源。
用这种方式,即使部分任务超时,你也能完整获取所有已完成请求的结果,同时可以明确标记出超时或失败的请求。
内容的提问来源于stack exchange,提问作者Abracadabraaa
相关产品推荐
相关产品推荐

