requests、httpx 与 aiohttp
三种 HTTP 客户端的传参、响应处理与异步调用说明。
| 库 | 调用方式 | 适用场景 |
|---|---|---|
| requests | 同步调用,等待期间阻塞当前线程 | 顺序执行的脚本、已有同步接口封装 |
| httpx | 同时提供同步与异步客户端 | 同一套项目需要两种调用方式,或需要 HTTP/2 |
| aiohttp | 基于 asyncio 的异步客户端 | 已有异步调用链,或需要内置 WebSocket 客户端 |
HTTP/1.1、HTTP/2 是 HTTP 协议的不同版本,本文示例默认使用 HTTP/1.1。HTTP/2 支持在同一条 TCP 连接上交错传输多个请求和响应;GET、POST 在两种版本中都可以使用。
1. 安装与示例接口
| |
示例使用 httpbin 公共回显服务,返回收到的参数、请求头和请求体;无需账号或密钥。公共服务可能暂时不可用,只提交示例数据。
验证环境:Python 3.13.11、requests 2.32.5、httpx 0.28.1、aiohttp 3.13.3。
2. requests:同步请求
2.1 GET:查询参数与请求头
| |
| |
requests.get():发送请求,返回响应对象。raise_for_status():检查状态码,4xx、5xx 时抛出异常。response.json():将响应体解析为 Python 对象。
params 对 GET、POST 都适用,始终放在 URL 查询字符串中。 POST 可以同时用 params 传查询参数,用 json 或 data 传请求体。
requests 的超时分为连接超时和读取超时,单位都是秒。
- 统一设置:
timeout=15,连接超时和读取超时都设为 15 秒,也可以传小数。 - 分别设置:
timeout=(5, 15),按(连接超时, 读取超时)排列,分别设为 5 和 15 秒。
读取超时限制等待下一段响应数据的时间,不等于整个请求的总时限。
2.2 POST:发送 JSON
| |
| |
- 请求体:
data=json.dumps(payload)先将字典转为 JSON 文本,再发送。 - 发送类型:
Content-Type: application/json声明请求体是 JSON。 - 接收类型:
Accept: application/json表示希望收到 JSON 响应。
也可以直接用 json=payload,由 requests 完成序列化并设置 JSON 内容类型;
注意: 不要写成 json=json.dumps(payload),否则会重复编码。
3. aiohttp:异步请求
| |
| |
外层 async with 负责关闭 Session,内层负责释放本次响应。
aiohttp 取得响应对象时,响应体可能尚未读完,因此 response.json() 需要 await。 raise_for_status() 只检查状态码,不需要 await。
4. httpx:同步与异步请求
4.1 同步版本
Client 管理公共配置和连接池:
| |
| |
4.2 异步版本
| |
| |
- 流式响应:用
aiter_bytes()逐块读取,边接收边处理;await response.aread()则读完整个响应体。 - JSON 文本:已经序列化的数据用
content=发送,并设置Content-Type: application/json。 - HTTP/2:安装
httpx[http2],创建客户端时设置http2=True;服务端也须支持,可用response.http_version查看实际协议。
5. 批量并发请求
三个请求共享一个 Session,最多同时执行两个:
| |
全部请求成功时:
| |
gather(*calls):并发调度协程,结果按输入顺序排列。Semaphore(2):限制同时进行的请求数,不限制每秒请求数。return_exceptions=True:将普通请求异常放入结果列表,其余请求继续完成。
httpx 的 AsyncClient 也可用同样方式调度,客户端在这一批请求之间共享。
6. 用法对照
6.1 响应属性和读取方式
| 操作 | requests | httpx | aiohttp |
|---|---|---|---|
| 状态码 | response.status_code | response.status_code | response.status |
| JSON | response.json() | response.json() | await response.json() |
| 文本 | response.text | response.text | await response.text() |
| 字节 | response.content | response.content | await response.read() |
6.2 超时设置对照
| 库 | 本文设置 | 含义 |
|---|---|---|
| requests | timeout=(5, 15) | 连接超时 5 秒,读取等待超时 15 秒 |
| httpx | httpx.Timeout(15, connect=5) | 连接超时 5 秒;读取、写入、等待连接池分别按 15 秒限制 |
| aiohttp | aiohttp.ClientTimeout(total=20, connect=5) | 整次请求总超时 20 秒;获取连接超时 5 秒,包含连接池排队和新连接建立 |
requests、httpx 按阶段限制超时,aiohttp 的
total限制整次请求;total不包含等待信号量的时间。默认值:requests 不设超时,httpx 各阶段 5 秒,aiohttp 总超时 300 秒。
6.3 HTTP 状态异常与网络异常
HTTP 状态异常由 raise_for_status() 触发。表中异常类属于对应客户端库,asyncio.TimeoutError 除外:
| 情况 | requests | httpx | aiohttp |
|---|---|---|---|
| 状态检查失败 | HTTPError,针对 4xx、5xx | HTTPStatusError,针对非 2xx | ClientResponseError,针对状态码 ≥ 400 |
| 连接错误 | ConnectionError | ConnectError | ClientConnectionError |
| 超时 | Timeout | TimeoutException | asyncio.TimeoutError,也能捕获总超时 |
requests 2.32.5 读取响应体超时时也可能抛 ConnectionError,只捕获 Timeout 无法覆盖这一情况。
requests、aiohttp 的 GET/POST 默认跟随重定向;httpx 默认不跟随,需要时设置 follow_redirects=True,否则 302 响应也会触发状态异常。
6.4 其他注意事项
verify=False、ssl=False会跳过 HTTPS 证书校验;证书错误应通过证书链或可信 CA 配置解决。- 在异步函数中直接调用 requests 仍会阻塞事件循环;可改用异步客户端,或交给
asyncio.to_thread()。 - POST 超时后,服务端可能已执行成功;重试前需确认接口的幂等或去重机制。
7. 捕获异常
具体异常写在前面,父类异常写在后面。 请求发送、状态检查和 JSON 解析都放进 try,分别处理失败原因。
以下脚本使用返回 404 的测试接口;换成返回 JSON 的正常接口后,会打印解析结果。异常在 main() 入口处理,前面用于返回数据的请求函数仍可让调用方处理异常。
7.1 requests
| |
| |
RequestException包括连接失败等请求异常,也包括前面几个异常,因此放在最后。
7.2 httpx
| |
| |
同步
Client使用相同的异常类型。
7.3 aiohttp
| |
| |
ContentTypeError是ClientResponseError的子类,需优先捕获;asyncio.TimeoutError用于覆盖总超时,不能只捕获ClientError。
8. 常见 HTTP 错误状态码
8.1 4xx:客户端错误
| 状态码 | 含义 |
|---|---|
| 400 | 请求有误,服务器无法或拒绝处理 |
| 401 | 缺少有效的身份凭据,例如未提供或已失效的 Token |
| 403 | 服务器理解请求,但因权限或其他策略拒绝执行 |
| 404 | 未找到目标资源,或服务器不愿透露其存在 |
| 405 | 目标资源不支持当前请求方法 |
| 408 | 服务器未在期限内收到完整请求 |
| 409 | 请求与资源当前状态冲突,例如更新版本冲突 |
| 415 | 请求体格式不受支持,例如接口要求 JSON,却提交了表单 |
| 422 | 内容类型、语法正确,但语义无法处理,例如字段值不符合要求 |
| 429 | 请求过于频繁,触发限流 |
8.2 5xx:服务端错误
| 状态码 | 含义 |
|---|---|
| 500 | 服务器内部发生意外错误 |
| 502 | 网关或代理收到上游服务器的无效响应 |
| 503 | 服务因临时过载或维护而不可用 |
| 504 | 网关或代理等待上游服务器响应超时 |
408、504 是服务端返回的 HTTP 状态码;客户端抛出 Timeout 时,可能根本没有收到 HTTP 响应。
评论
使用 GitHub 登录后参与讨论,评论将公开保存在 GitHub。
站长管理删除会同步到 GitHub,无法撤销。
阅读到这里时加载评论。