ThreadPoolExecutor配合Python Requests使用时仅首个请求可被as_completed捕获
问题修复方案
根因分析
- 异常捕获范围不完整是核心问题:你当前仅捕获了
HTTPError、ConnectionError、ConnectTimeout三类异常,但requests请求及结果处理过程中可能抛出的异常类型远多于上述三类(如ReadTimeout、SSLError、JSONDecodeError等)。一旦某个任务返回的异常不在你的捕获列表中,as_completed的遍历循环就会直接终止,主线程不再处理后续已完成的任务,但线程池内的剩余任务还会继续执行,所以会出现持续打印here但不再打印right here的现象。 - 次要问题:你没有给
requests.get设置超时参数,可能导致个别请求无限挂起占用工作线程;另外load_url内和as_completed分支内重复调用r.json()属于冗余操作,极端情况下可能因响应流关闭触发异常。
修复代码
第一步:导入必要依赖
import requests import concurrent.futures # 直接导入requests基异常,可覆盖所有请求相关异常 from requests.exceptions import RequestException
第二步:优化请求函数
def load_url(url): print("here") # 增加超时参数,避免请求无限挂起 r = requests.get(url, timeout=10) print(r.url) # 提前解析JSON并存储,避免重复解析 json_data = r.json() print(json_data) return r, json_data
第三步:优化主逻辑异常处理
def main(): urls = ["example1.com", "example2.com", "example3.com"] # 实际为1500条URL with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: future_to_url = {executor.submit(load_url, url): url for url in urls} for future in concurrent.futures.as_completed(future_to_url): print("right here") url = future_to_url[future] try: response, json_data = future.result() # 捕获所有requests相关异常 except RequestException as e: print(f"{url} 请求失败:{str(e)}") # 兜底捕获其他未知异常,避免循环意外终止 except Exception as e: print(f"{url} 处理异常:{str(e)}") else: print(json_data) if __name__ == "__main__": main()
内容的提问来源于stack exchange,提问作者Andrew Pulver
相关产品推荐
相关产品推荐

