Python使用asyncio+aiohttp实现高效异步并发下载

作者:

文章目录
  • aiohttp 是基于 asyncio 的高性能异步 HTTP 客户端/服务器框架; 支持异步请求、自动连接池、重定向、超时控制; 语法简洁,性能远超多线程或同步方案; 适合 I/O 密集型任务(如网络下载)。 注意:Python 的“异步” ≠ “多线程”,它是通过事件循环(Event Loop)在单线程中并发处理多个 I/O 操作,避免阻塞。
  • 首先安装 aiohttp(若未安装): pip install aiohttp 推荐同时安装 aiofiles(用于异步写入文件): pip install aiofiles
  • 方式 3 个 50MB 文件耗时(估算) 同步下载(requests) ~45 秒 多线程(ThreadPoolExecutor) ~20 秒 异步下载(aiohttp + asyncio) ~15–18 秒 实际提升取决于网络带宽和服务器并发能力。异步方案在高延迟或大量小文件场景下优势更明显。
  • 1.限制并发数量 若 URL 数量极大(如 1000+),可使用 asyncio.Semaphore 控制并发数,避免打爆目标服务器或本地资源: semaphore = asyncio.Semaphore(10) # 最多 10 个并发 async def download_file_limited(session, url, filename): async with semaphore: await download_file(session, url, filename) 2.添加 User-Agent 和超时 timeout = aiohttp.ClientTimeout(total=30) async with aiohttp.ClientSession( timeout=timeout, headers={“User-Agent”: “Mozilla/5.0 (Python aiohttp)”} ) as session: 3.自动从 URL 提取文件名 from urllib.parse import urlparse import os def get_filename_from_url(url): path = urlparse(url).path name = os.path.basename(path) return name if name else “downloaded_file”
  • 使用 asyncio + aiohttp 是 Python 实现高并发下载的最佳实践; 异步下载能显著提升效率,尤其适合批量、I/O 密集型任务; 对于大文件,推荐使用流式下载 + aiofiles 避免内存溢出; 生产环境中务必加入错误处理、超时控制、并发限制。 掌握这套异步下载方案,你就能轻松应对各种批量资源采集、自动化备份、数据同步等需求! 到此这篇关于Python使用asyncio+aiohttp实现高效异步并发下载的文章就介绍到这了,更多相关Python异步并发下载内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: 使用Python实现带进度条的异步多文件下载器 python 并发下载器实现方法示例 python基于gevent实现并发下载器代码实例 Python 异步编程 asyncio简介及基本用法 Python中asyncio库实现异步编程的示例 Python使用asyncio实现异步操作的示例
  • 目录
    • 一、为什么选择 aiohttp + asyncio
    • 二、安装依赖
    • 三、核心代码实现
      • 方法一:将内容全部加载到内存后保存(适合中小文件)
      • 方法二:流式下载(适合大文件,节省内存)
    • 四、性能优势对比
      • 五、进阶优化建议
        • 六、总结

          在处理多个远程文件下载任务时,如果采用传统的同步方式(如 requests.get() 逐个下载),程序会因等待网络 I/O 而长时间阻塞,效率极低。

          本文将教你如何使用 Python 的异步编程模型(asyncio)配合 aiohttp 库,实现真正高效的异步并发下载,大幅提升下载速度,尤其适用于批量下载图片、视频、压缩包等场景。

          • aiohttp 是基于 asyncio 的高性能异步 HTTP 客户端/服务器框架;
          • 支持异步请求、自动连接池、重定向、超时控制;
          • 语法简洁,性能远超多线程或同步方案;
          • 适合 I/O 密集型任务(如网络下载)。

          注意:Python 的“异步” ≠ “多线程”,它是通过事件循环(Event Loop)在单线程中并发处理多个 I/O 操作,避免阻塞。

          首先安装 aiohttp(若未安装):

          pip install aiohttp
          

          推荐同时安装 aiofiles(用于异步写入文件):

          pip install aiofiles
          

          import asyncio
          import aiohttp
          import os
          
          async def download_file(session, url, filename):
              """异步下载单个文件"""
              try:
                  async with session.get(url) as response:
                      if response.status == 200:
                          content = await response.read()
                          with open(filename, 'wb') as f:
                              f.write(content)
                          print(f"✅ 下载成功: {filename}")
                      else:
                          print(f"❌ 下载失败 ({response.status}): {url}")
              except Exception as e:
                  print(f"⚠️  下载出错: {url} | 错误: {e}")
          
          async def download_all(urls, folder="downloads"):
              """并发下载多个文件"""
              os.makedirs(folder, exist_ok=True)
          
              # 创建 aiohttp 客户端会话(支持连接复用)
              async with aiohttp.ClientSession() as session:
                  tasks = []
                  for i, url in enumerate(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)
          
                  # 并发执行所有下载任务
                  await asyncio.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 镜像),建议使用流式写入,避免一次性加载整个文件到内存:

          import aiofiles  # 需要额外安装
          
          async def download_file_stream(session, url, filename):
              try:
                  async with session.get(url) as response:
                      if response.status == 200:
                          async with aiofiles.open(filename, 'wb') as f:
                              async for chunk in response.content.iter_chunked(8192):
                                  await f.write(chunk)
                          print(f"✅ 流式下载成功: {filename}")
                      else:
                          print(f"❌ 下载失败 ({response.status}): {url}")
              except Exception as e:
                  print(f"⚠️  流式下载出错: {url} | 错误: {e}")
          
          # 在 download_all 中替换 download_file 为 download_file_stream 即可
          

          方式 3 个 50MB 文件耗时(估算)
          同步下载(requests) ~45 秒
          多线程(ThreadPoolExecutor) ~20 秒
          异步下载(aiohttp + asyncio) ~15–18 秒

          实际提升取决于网络带宽和服务器并发能力。异步方案在高延迟或大量小文件场景下优势更明显。

          1.限制并发数量

          若 URL 数量极大(如 1000+),可使用 asyncio.Semaphore 控制并发数,避免打爆目标服务器或本地资源:

          semaphore = asyncio.Semaphore(10)  # 最多 10 个并发
          
          async def download_file_limited(session, url, filename):
              async with semaphore:
                  await download_file(session, url, filename)
          

          2.添加 User-Agent 和超时

          timeout = aiohttp.ClientTimeout(total=30)
          async with aiohttp.ClientSession(
              timeout=timeout,
              headers={"User-Agent": "Mozilla/5.0 (Python aiohttp)"}
          ) as session:
          

          3.自动从 URL 提取文件名

          from urllib.parse import urlparse
          import os
          
          def get_filename_from_url(url):
              path = urlparse(url).path
              name = os.path.basename(path)
              return name if name else "downloaded_file"
          

          • 使用 asyncio + aiohttp 是 Python 实现高并发下载的最佳实践
          • 异步下载能显著提升效率,尤其适合批量、I/O 密集型任务;
          • 对于大文件,推荐使用流式下载 + aiofiles 避免内存溢出;
          • 生产环境中务必加入错误处理、超时控制、并发限制

          掌握这套异步下载方案,你就能轻松应对各种批量资源采集、自动化备份、数据同步等需求!

          到此这篇关于Python使用asyncio+aiohttp实现高效异步并发下载的文章就介绍到这了,更多相关Python异步并发下载内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

          您可能感兴趣的文章:

          • 使用Python实现带进度条的异步多文件下载器
          • python 并发下载器实现方法示例
          • python基于gevent实现并发下载器代码实例
          • Python 异步编程 asyncio简介及基本用法
          • Python中asyncio库实现异步编程的示例
          • Python使用asyncio实现异步操作的示例

          站内搜索