使用Python asyncio异步HTTP请求报错及tqdm进度条实现问题
问题解决与优化方案
一、事件循环报错的解决
报错There is no current event loop是因为Python3.7+推荐使用asyncio.run()启动异步程序,它会自动创建、管理和关闭事件循环,替代旧的get_event_loop()写法,同时避免环境差异导致的无默认循环问题。
另外,原代码中同步文件写入会阻塞事件循环,需要改用异步文件操作库aiofiles来保证异步效率。
二、集成tqdm异步进度条
使用tqdm的异步扩展asyncio.tqdm,可以直接包装asyncio.gather实现批量任务的进度显示,无需手动更新。
修改后的完整代码
首先安装依赖:
pip install aiohttp aiofiles tqdm
import aiohttp import asyncio import aiofiles from tqdm.asyncio import tqdm async def save_file(row, file_path): # 改用异步文件写入,避免阻塞事件循环 async with aiofiles.open(file_path, 'w', encoding='utf-8') as f: await f.write(row) async def download_html(session, url_idx, url): # 复用全局ClientSession,提升连接效率 async with session.get(url) as resp: if resp.status != 200: print(f"URL {url} 请求失败,状态码: {resp.status}") return body = await resp.text() # 替换为你的实际文件路径逻辑 file_path = f"output_{url_idx}.html" # 你的爬虫解析逻辑示例(替换成自己的代码) scrap_result = f"URL: {url}\n页面长度: {len(body)}\n" await save_file(scrap_result, file_path) async def main(): urls = ['url1', 'url2', 'url3'] # 全局创建一个ClientSession,所有任务复用 async with aiohttp.ClientSession() as session: tasks = [ download_html(session, url_idx, url) for url_idx, url in enumerate(urls) ] # 使用tqdm异步进度条执行所有任务 await tqdm.gather(*tasks, total=len(urls), desc="爬取进度") if __name__ == "__main__": # Python3.7+ 标准异步启动方式 asyncio.run(main())
关键修改说明
- 事件循环启动:用
asyncio.run(main())替代旧的get_event_loop()写法,适配所有Python3.7+环境。 - 异步文件操作:用
aiofiles.open替换同步open,避免IO阻塞拖慢异步效率。 - ClientSession复用:全局创建一个Session,所有下载任务共享,减少连接建立开销,提升爬取速度。
- tqdm进度条:通过
tqdm.asyncio.tqdm.gather直接包装任务列表,自动显示批量任务的进度百分比、剩余时间等信息。
内容的提问来源于stack exchange,提问作者ahgarawani
相关产品推荐
相关产品推荐

