AI Agent能力扩展三要素:Skill、MCP与插件的分层协同
2026/10/31 9:30:28
在处理多个远程文件下载任务时,如果采用传统的同步方式(如requests.get()逐个下载),程序会因等待网络 I/O 而长时间阻塞,效率极低。
本文将教你如何使用Python 的异步编程模型(asyncio)配合aiohttp库,实现真正高效的异步并发下载,大幅提升下载速度,尤其适用于批量下载图片、视频、压缩包等场景。
aiohttp是基于asyncio的高性能异步 HTTP 客户端/服务器框架;💡 注意:Python 的“异步” ≠ “多线程”,它是通过事件循环(Event Loop)在单线程中并发处理多个 I/O 操作,避免阻塞。
首先安装aiohttp(若未安装):
pipinstallaiohttp推荐同时安装
aiofiles(用于异步写入文件):pipinstallaiofiles
importasyncioimportaiohttpimportosasyncdefdownload_file(session,url,filename):"""异步下载单个文件"""try:asyncwithsession.get(url)asresponse:ifresponse.status==200:content=awaitresponse.read()withopen(filename,'wb')asf:f.write(content)print(f"✅ 下载成功:{filename}")else:print(f"❌ 下载失败 ({response.status}):{url}")exceptExceptionase:print(f"⚠️ 下载出错:{url}| 错误:{e}")asyncdefdownload_all(urls,folder="downloads"):"""并发下载多个文件"""os.makedirs(folder,exist_ok=True)# 创建 aiohttp 客户端会话(支持连接复用)asyncwithaiohttp.ClientSession()assession:tasks=[]fori,urlinenumerate(urls):# 生成文件名(可根据需要自定义)ext=os.path.splitext(url.split('?')[0])[-1]or'.bin'filename=os.path.join(folder,f"file_{i+1}{ext}")task=asyncio.create_task(download_file(session,url,filename))tasks.append(task)# 并发执行所有下载任务awaitasyncio.gather(*tasks)# 使用示例if__name__=="__main__":urls=["https://example.com/file1.zip","https://example.com/file2.jpg","https://example.com/file3.pdf",]print("🚀 开始异步下载...")asyncio.run(download_all(urls))print("🎉 所有文件下载完成!")对于大文件(如视频、ISO 镜像),建议使用流式写入,避免一次性加载整个文件到内存:
importaiofiles# 需要额外安装asyncdefdownload_file_stream(session,url,filename):try:asyncwithsession.get(url)asresponse:ifresponse.status==200:asyncwithaiofiles.open(filename,'wb')asf:asyncforchunkinresponse.content.iter_chunked(8192):awaitf.write(chunk)print(f"✅ 流式下载成功:{filename}")else:print(f"❌ 下载失败 ({response.status}):{url}")exceptExceptionase:print(f"⚠️ 流式下载出错:{url}| 错误:{e}")# 在 download_all 中替换 download_file 为 download_file_stream 即可| 方式 | 3 个 50MB 文件耗时(估算) |
|---|---|
| 同步下载(requests) | ~45 秒 |
| 多线程(ThreadPoolExecutor) | ~20 秒 |
| 异步下载(aiohttp + asyncio) | ~15–18 秒 |
📌 实际提升取决于网络带宽和服务器并发能力。异步方案在高延迟或大量小文件场景下优势更明显。
限制并发数量
若 URL 数量极大(如 1000+),可使用asyncio.Semaphore控制并发数,避免打爆目标服务器或本地资源:
semaphore=asyncio.Semaphore(10)# 最多 10 个并发asyncdefdownload_file_limited(session,url,filename):asyncwithsemaphore:awaitdownload_file(session,url,filename)添加 User-Agent 和超时
timeout=aiohttp.ClientTimeout(total=30)asyncwithaiohttp.ClientSession(timeout=timeout,headers={"User-Agent":"Mozilla/5.0 (Python aiohttp)"})assession:自动从 URL 提取文件名
fromurllib.parseimporturlparseimportosdefget_filename_from_url(url):path=urlparse(url).path name=os.path.basename(path)returnnameifnameelse"downloaded_file"asyncio + aiohttp是 Python 实现高并发下载的最佳实践;掌握这套异步下载方案,你就能轻松应对各种批量资源采集、自动化备份、数据同步等需求!