grequests批量请求600个URL偶发阻塞,如何设置单请求超时?
解决grequests批量请求时因少数请求无响应导致的阻塞问题
你的判断没错,卡住的原因就是少数请求未收到响应,导致grequests.map()一直等待所有请求完成。解决方法很直接:给每个请求设置单个超时时间,让超时的请求主动终止,不再阻塞整体流程。
1. 给单个请求添加超时参数
grequests.get()支持timeout参数,直接在创建请求时指定最长等待时间(单位:秒),超时后请求会抛出异常并终止,不会一直挂着。
修改后的代码如下:
l = [] urls = [...] # 给每个GET请求设置5秒超时,可根据需求调整时长 reqs = [grequests.get(i, timeout=5) for i in urls] rs = grequests.map(reqs) print('done')
2. 进阶:控制并发数与异常处理
如果600个请求并发量太高,也可能导致部分请求响应缓慢或超时。可以通过grequests.map()的size参数限制并发数,同时添加异常处理器,更清晰地处理超时或失败的请求:
def exception_handler(request, exception): print(f"请求 {request.url} 失败: {str(exception)}") return None # 可自定义返回值,比如空字典 l = [] urls = [...] reqs = [grequests.get(i, timeout=5) for i in urls] # 限制并发数为20,同时指定异常处理器 rs = grequests.map(reqs, size=20, exception_handler=exception_handler) print('done') # 遍历结果,区分成功响应和失败/超时的请求 for idx, resp in enumerate(rs): if resp is not None and resp.status_code == 200: print(f"URL {urls[idx]} 请求成功") else: print(f"URL {urls[idx]} 请求失败或超时")
原理说明
timeout参数会让单个请求在指定时间内未收到响应时,触发requests.exceptions.Timeout异常,grequests.map()会捕获该异常,不会让整个程序卡住。size参数控制同时发起的请求数量,避免一次性发起600个请求导致的网络拥堵,提升整体请求稳定性。
内容的提问来源于stack exchange,提问作者ZhaiShang
相关产品推荐
相关产品推荐

