Python asyncio使用run_in_executor时无法获取scraper返回结果列表的问题
代码运行异常的根因
存在的核心问题
get_toner函数调用loop.run_in_executor后,没有将该方法返回的Future对象向外传递,所有提交到executor的任务都作为临时值被丢弃,无法进入后续的结果收集链路。- 读取事件循环任务集合的时机错误:刚提交完所有executor调用、任务还未被事件循环正式调度时,就调用
asyncio.all_tasks(loop)获取任务列表,此时拿到的是空集合,最终gather收集到的自然是空列表。 - 缺少
executor的实际初始化逻辑,直接使用未定义的executor对象会直接触发运行报错。
可正常运行的修正代码
import asyncio from concurrent.futures import ThreadPoolExecutor # 初始化线程池,可根据爬取需求调整并发数 executor = ThreadPoolExecutor(max_workers=10) loop = asyncio.get_event_loop() def get_toner(url, loop): # 必须将run_in_executor返回的Future对象返回,供外部收集 return loop.run_in_executor(executor, scraper, url) def scraper(url): # 原有爬取逻辑,返回对应打印机的墨粉余量百分比 pass def main(): task_list = [] for stampante in lista_totale: # 逐次将生成的executor任务存入列表 task_list.append(get_toner(stampante, loop=loop)) # 等待所有任务执行完成后统一收集返回结果 lista_verificati = loop.run_until_complete(asyncio.gather(*task_list)) print(lista_verificati) if __name__ == "__main__": main()
实操注意点
- 不要依赖
asyncio.all_tasks()凑待收集的任务列表,提交任务阶段就要手动持有所有任务的引用,避免非预期的任务遗漏。 - 线程池并发数不要设置过高,否则会触发目标打印机Web服务的访问限流,导致爬取失败。
- Python 3.7及以上版本可直接使用
asyncio.run()替代手动获取、管理事件循环的写法,减少循环生命周期管理的出错概率。
内容的提问来源于stack exchange,提问作者Gian76
相关产品推荐
相关产品推荐

