如何为aiometer的run_all方法实现异步进度条?
如何为aiometer的run_all方法实现异步进度条?
我刚好也遇到过类似的困扰,直接套用asyncio.gather搭配tqdm的方式确实没法适配aiometer的任务管理逻辑。不过我们可以通过给每个任务包装一层进度更新的逻辑,结合tqdm的异步版本来解决这个问题,具体步骤如下:
1. 准备工作:导入tqdm的异步模块
首先确保你已经安装了tqdm,然后导入它的异步专用模块:
from tqdm.asyncio import tqdm_asyncio
2. 包装任务,添加进度更新逻辑
我们需要把原来的get_donations任务包装成一个新的异步函数,让每个任务完成后(无论成功还是失败)都去更新进度条:
from functools import partial from asyncio import run from aiometer import run_all from tqdm.asyncio import tqdm_asyncio async def main(): total_pages = 50 # 初始化异步进度条,设置总任务数和描述文本 progress_bar = tqdm_asyncio(total=total_pages, desc="正在处理捐赠数据") # 包装任务函数,完成后更新进度条 async def wrapped_task(page): try: await ApiGuara.get_donations(page) finally: # 不管任务成功还是失败,都更新进度条 progress_bar.update(1) # 生成包装后的任务列表 tasks = [wrapped_task(page) for page in range(total_pages)] # 用aiometer的run_all执行任务,保持原有的并发限制 await run_all(tasks, max_at_once=10) # 任务全部完成后关闭进度条 progress_bar.close() run(main())
3. 小优化:简化你的get_donations方法
顺便提个小细节,你的get_donations方法里,async with AsyncClient(...) as asyncclient:已经会自动管理客户端的生命周期,块结束时会自动关闭客户端,所以finally里的await asyncclient.aclose()是多余的,可以删掉,简化后的代码如下:
async def get_donations(self, page:int) -> None: async with AsyncClient( base_url=f'{self.url}', headers=self.headers, timeout=None ) as asyncclient: try: r = await asyncclient.get(f'/donations?page={page}') donations_json = r.json()['data'] for donation in donations_json: donation['_id'] = donation.pop('id') try: # DONATIONS_COLLECTION.insert_one(donation) pass except errors.DuplicateKeyError: pass # 这里可以根据需要捕获其他API请求相关的异常 except Exception as e: print(f"处理第{page}页时出错: {str(e)}")
这样修改后,进度条就能正常跟随aiometer的任务执行节奏更新了,既保留了run_all的并发控制能力,又能直观看到任务执行进度。
备注:内容来源于stack exchange,提问作者Fábio Marane
相关产品推荐
相关产品推荐

