如何在磁盘剩余空间达标前持续给asyncio.gather追加下载任务?
解决方案
要实现「一个文件夹下载完成后立即启动下一个,磁盘剩余空间不足200GB时停止提交新任务但完成现有任务」的需求,可以用信号量控制并发数+逐个迭代提交任务的方式替代原有的分块批量等待逻辑,具体实现如下:
修改后的代码
import asyncio import aiohttp from aioshutil import disk_usage async def bounded_download(folder, session, semaphore): async with semaphore: await download_folder(folder, session) async def main(): # 控制同时运行的下载任务数量(和原逻辑的每组100个保持一致) semaphore = asyncio.Semaphore(100) tasks = [] async with aiohttp.ClientSession() as session: for folder in folders_to_download: # 检查磁盘剩余空间(转换为GB) total, used, free = await disk_usage("/media/hdd") free_gb = free / (10**9) if free_gb < 200: print(f"磁盘剩余空间不足200GB(当前{free_gb:.2f}GB),停止提交新任务") break # 提交新的下载任务,信号量会自动控制并发数 task = asyncio.create_task(bounded_download(folder, session, semaphore)) tasks.append(task) # 等待所有已提交的任务全部完成 await asyncio.gather(*tasks)
关键逻辑说明
- 并发数控制:用
asyncio.Semaphore(100)限制同时运行的下载任务不超过100个,和原逻辑的分块大小一致,但无需等待整组完成——只要有一个任务结束释放信号量,下一个任务就会立即启动。 - 磁盘空间检查时机:每次提交新任务前都检查剩余空间,一旦不足200GB就停止迭代,不再提交新任务。
- Session复用:将
ClientSession放在循环外复用,避免频繁创建销毁会话带来的性能开销。 - 任务跟踪与收尾:用列表收集所有已启动的任务,最后通过
asyncio.gather等待全部完成,确保已开始的下载任务都能正常结束。
对原代码的优化点
- 去掉了numpy分块的逻辑,改为逐个迭代文件夹,实现任务的无缝衔接
- 解决了原逻辑中「必须等整组完成才能开始下一组」的效率问题
- 更及时的磁盘空间检查,避免提交不必要的任务
- 复用ClientSession,提升整体下载效率
内容的提问来源于stack exchange,提问作者janbmull
相关产品推荐
相关产品推荐

