登录
首页 >  文章 >  python教程

Pythonaiohttp异步请求入门教程

时间:2026-02-06 18:09:42 370浏览 收藏

本篇文章向大家介绍《Python aiohttp异步请求教程》,主要包括,具有一定的参考价值,需要的朋友可以参考一下。

aiohttp.ClientSession 必须复用,因新建会重复初始化连接池、SSL 上下文并绑定事件循环,导致开销大、RuntimeError、连接泄漏及文件描述符耗尽;应全局单例创建,用 async with 包裹单次请求。

Python aiohttp 异步请求的实践指南

为什么 aiohttp.ClientSession 必须复用,不能每次请求都新建

因为新建 ClientSession 会重新初始化连接池、SSL 上下文和事件循环绑定,不仅开销大,还会导致 RuntimeError: Session is closed 或连接泄漏。尤其在高并发场景下,频繁创建销毁 session 容易触发文件描述符耗尽(OSError: [Errno 24] Too many open files)。

实操建议:

  • 全局或作用域内只创建一次 ClientSession,用 async with 仅包裹单次请求逻辑,不是整个 session 生命周期
  • 若需定制超时或 headers,统一在 session 初始化时传入 timeoutheaders 参数,而非每个 session.get() 都重复指定
  • 在 Web 应用(如 FastAPI)中,通过 lifespan hook 或依赖注入管理 session 生命周期,避免在路由函数里现场 new

aiohttp 中如何正确处理 JSON 响应和编码问题

直接调用 response.json() 看似方便,但默认不校验 Content-Type,且对非 UTF-8 编码(如 GBK、ISO-8859-1)会抛 UnicodeDecodeError。更隐蔽的问题是:某些 API 返回 text/plain 但内容实为 JSON 字符串,此时 .json() 会静默失败或解析出错。

实操建议:

  • 优先用 await response.text(encoding="utf-8") 拿原始字符串,再用 json.loads() 显式解析,便于捕获和调试格式错误
  • 若响应头含 charset=gbk,必须显式传 encoding:await response.text(encoding="gbk"),不能依赖自动探测
  • 对不确定 content-type 的接口,先打印 response.content_typeresponse.charset 调试,再决定解析路径

并发请求控制:用 asyncio.Semaphore 还是 aiohttp.TCPConnectorlimit

两者都管并发,但作用层级不同:TCPConnector(limit=10) 控制的是底层 TCP 连接数上限,影响复用和端口占用;Semaphore 控制的是协程并发数,影响任务调度节奏。混用时若配置冲突(比如 semaphore=5 但 connector.limit=100),实际并发仍受更严的那个限制。

实操建议:

  • 优先用 TCPConnector(limit=20, limit_per_host=5) —— 它能真正防止对单个 host 建连风暴,比纯协程限流更贴近网络层实际压力
  • 需要业务级节流(如每秒最多调 3 次某 API)时,才叠加 Semaphore,且注意把它定义在 session 外部,避免每次请求都 new 一个新实例
  • 不要设 limit=0(无限制),Linux 默认单进程最大 socket 数约 1024,超出会报 OSError: [Errno 24]

异常捕获必须覆盖的三个关键点

aiohttp 的异常分散在多个层级:DNS 解析失败(aiohttp.ClientConnectorError)、连接超时(asyncio.TimeoutError)、HTTP 状态码非 2xx(response.raise_for_status()aiohttp.ClientResponseError)。漏掉任意一类,都会让程序意外中断。

实操建议:

  • 外层用 try/except (aiohttp.ClientError, asyncio.TimeoutError) as e: 捕获网络层异常
  • 内层对每个 response 显式调用 response.raise_for_status(),否则 404、502 等状态码不会抛异常,容易误判为成功
  • 记录异常时务必包含 str(e)response.url if "response" in locals() else None,否则排查时不知道失败发生在哪个 URL
实际项目里最常被忽略的是 connector 复用和 charset 显式声明——前者导致压测时连接数飙升,后者让中文字段突然变成乱码且难以复现。这两处不改,其他优化意义不大。

本篇关于《Pythonaiohttp异步请求入门教程》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于文章的相关知识,请关注golang学习网公众号!

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>