VOLTTRON代理使用grequests实现异步HTTP请求时status_code属性缺失报错咨询
报错核心原因
两处API使用错位直接触发了属性不存在的报错:
grequests.get()入参逻辑错误:grequests本身是基于gevent的异步请求构造工具,要求入参为目标URL字符串,不需要嵌套普通requests.get()的同步调用结果。当前代码把simple_request()执行后的同步Response对象传给grequests.get(),构造逻辑完全不符合grequests的设计预期。grequests.send()返回值认知错误:该方法的作用是将构造好的异步请求提交到gevent协程池执行,返回值是对应执行HTTP请求的Greenlet协程对象,本身不直接携带HTTP响应属性。要获取真实响应,需要等协程执行完毕后,从协程的value属性中提取。
异步能力适配说明
不需要对requests库做额外封装来实现grequests异步能力:
- grequests本身就是基于gevent对requests做的异步适配层,只要正确调用API,就可以完全匹配VOLTTRON平台的协程调度模型——VOLTTRON本身就是基于gevent实现事件驱动的VIP消息交互,和grequests的非阻塞IO运行逻辑完全兼容,不会阻塞平台的消息循环。
- 对于单次HTTP请求的场景,只要不走同步requests的阻塞调用路径,用grequests发起的请求本身就是异步非阻塞的,完全满足平台对代理代码异步性的要求。
修正后的VOLTTRON代理代码实现
def cron_function(self): _log.info(f'*** [grequests INFO] *** - starting CRON Processes') # 直接传入URL构造grequests异步请求对象 async_request = grequests.get(self.url1) _log.info(f'*** [grequests INFO] *** - sending out {async_request}') # 提交请求到协程池执行,返回Greenlet协程对象 greenlet_task = grequests.send(async_request) # 等待协程执行完成(gevent协程的等待是主动让出调度权的非阻塞等待,不会卡住平台主流程) greenlet_task.join() # 从协程返回值中获取真实的HTTP响应对象 response = greenlet_task.value _log.info(f'*** [grequests INFO] *** - response code {response.status_code}') _log.info(f'*** [grequests INFO] *** - response text {response.content}')
平台使用注意事项
- 若后续需要并行发起多个HTTP请求,可直接用
grequests.map()批量提交请求列表,一次等待所有响应返回,比逐个管理协程的效率更高。 - 代理中引入grequests不需要额外做平台级适配改造,安装依赖时把grequests加入代理的requirements列表即可正常运行。
内容的提问来源于stack exchange,提问作者bbartling
相关产品推荐
相关产品推荐

