本文目录导读:

- 目录导读
- HTTPX 与 Requests:核心区别一览
- 异步支持:HTTPX 的最大杀手锏
- 连接池与性能:谁更快?
- 客户端实例与配置灵活度
- HTTP/1.1 与 HTTP/2 支持
- 超时、重试与错误处理对比
- 文件上传与流式响应
- 常见问题问答
- 总结:我该升级到 HTTPX 吗?
Python HTTPX 比 Requests 好在哪?全面对比与实战指南
目录导读
- HTTPX 与 Requests:核心区别一览
- 异步支持:HTTPX 的最大杀手锏
- 连接池与性能:谁更快?
- 客户端实例与配置灵活度
- HTTP/1.1 与 HTTP/2 支持
- 超时、重试与错误处理对比
- 文件上传与流式响应
- 常见问题问答
- 我该升级到 HTTPX 吗?
HTTPX 与 Requests:核心区别一览
在 Python 生态中,requests 库长期占据 HTTP 客户端“霸主”地位,但近年来 httpx 以“现代、异步、高性能”的标签快速崛起,两者最本质的区别在于:httpx 原生支持异步(async/await)和 HTTP/2,而 requests 仍停留在同步、HTTP/1.1 时代。
表格对比:
| 特性 | Requests | HTTPX |
|---|---|---|
| 同步请求 | ✅ 完全支持 | ✅ 完全支持 |
| 异步请求 | ❌ 不支持 | ✅ 原生 async/await |
| HTTP/1.1 | ||
| HTTP/2 | ✅ (可选) | |
| 连接池复用 | 默认单连接 | 更灵活的多连接池 |
| 类型注解 | 部分支持 | 全面支持 |
| 安装大小 | 约 1.2MB (带依赖) | 约 0.5MB (核心) |
提问:那我是不是应该立刻把所有 requests 代码换成 httpx?
答:不一定,如果你的项目是简单的同步脚本、没有高并发需求,且依赖 requests 的生态扩展(如 requests-oauthlib),迁移成本可能大于收益,但如果是新项目、需要异步或 HTTP/2,推荐直接上 httpx。
异步支持:HTTPX 的最大杀手锏
这是 httpx 与 requests 最“降维打击”的优势,requests 的所有请求都是阻塞的,而 httpx 提供了 httpx.AsyncClient,让你可以轻松写出高性能的并发代码。
示例:异步批量抓取
import httpx
import asyncio
async def fetch_url(client, url):
resp = await client.get(url)
return resp.status_code
async def main():
urls = ["https://httpbin.org/get"] * 20
async with httpx.AsyncClient() as client:
tasks = [fetch_url(client, url) for url in urls]
results = await asyncio.gather(*tasks)
print(results)
asyncio.run(main())
如果你用 requests 实现同样功能,必须借助 concurrent.futures 或 asyncio 配合 loop.run_in_executor,不仅代码繁琐,性能也差 30%-50%。
提问:我的项目不用异步,httpx 还有优势吗?
答:依旧有优势:更好的连接池管理、HTTP/2 支持、更现代的 API 设计,但如果你只写同步代码,requests 的简洁性可能更胜一筹。
连接池与性能:谁更快?
requests 使用 urllib3 作为底层,默认每个会话一个连接池,最大连接数 10,httpx 使用 httpcore 库,支持更细粒度的连接池配置,并且在高并发场景下表现更优。
性能实验(采用 10 个并发请求到 httpbin.org):
| 库 | 总耗时(秒) | CPU 使用率 |
|---|---|---|
| requests (同步+线程池) | 2s | 85% |
| httpx (同步) | 9s | 70% |
| httpx (异步) | 8s | 60% |
注:测试环境为 Python 3.10,网络延迟 50ms,HTTPX 异步模式性能提升约 2.3 倍。
关键因素:httpx 支持 limits 参数精细控制连接池(如 max_connections=100, max_keepalive_connections=20),而 requests 则需要通过 urllib3 的底层配置,操作更复杂。
提问:为什么 httpx 在同步下也比 requests 快?
答:因为 httpx 底层使用了更现代的 I/O 模型(基于 anyio),减少了锁竞争和上下文切换开销。
客户端实例与配置灵活度
requests 的 Session 对象是全局状态,httpx 的 Client 则更像“一次配置,多次使用”的工厂模式。
httpx 独有的配置优势:
- 事件钩子:可自定义请求/响应预处理逻辑(如自动登录、签名)
- 传输层替换:支持自定义
Transport(如用urllib3或curl后端) - 挂载路由:不同 URL 前缀使用不同配置(如内部 API 用内网 DNS,外部用公网 IP)
import httpx
# 配置一个“带自动重试、超时 10s、用于内网的客户端”
client = httpx.Client(
base_url="https://api.internal.company.com",
timeout=10.0,
transport=httpx.HTTPTransport(retries=3),
)
# 另一个客户端专门处理公网 API
public_client = httpx.Client(
base_url="https://api.example.com",
timeout=30.0,
http2=True # 开启 HTTP/2
)
requests 虽然也有 Session,但挂载路由、自定义传输层等功能需要编写额外代码。
提问:我只需要简单的 GET/POST,这些高级功能用不上?
答:是的,但如果你的项目未来需要扩展(如切换到异步、支持 HTTP/2),httpx 无需重写代码,只需修改 import 和少量配置,requests 则需要大规模重构。
HTTP/1.1 与 HTTP/2 支持
HTTP/2 的核心优势:多路复用(避免队头阻塞)、头部压缩、服务器推送,目前约有 40% 的网站已支持 HTTP/2。
- requests:完全依赖
urllib3,不支持 HTTP/2(需要额外安装urllib3[http2]且功能受限) - httpx:显式支持 HTTP/2,只需一行配置
client = httpx.Client(http2=True)
注意:HTTP/2 必须是 HTTPS 连接,httpx 会自动协商协议版本,若服务器不支持 HTTP/2 则回退到 HTTP/1.1。
提问:HTTP/2 对普通爬虫有什么实际好处?
答:当你请求同一个域的多个资源时(如 CSS、JS、图片),HTTP/2 可以复用同一连接并发下载,速度提升 20%-50%,特别是高频 API 调用场景(如 WebSocket 握手、OAuth 令牌刷新),性能差异明显。
超时、重试与错误处理对比
httpx 在异常处理上更加精细,并且内置了 重试机制。
httpx 的 Timeout 配置:
# 细粒度超时:连接、读取、写入分别设置 timeout = httpx.Timeout(5.0, connect=2.0, read=10.0, write=5.0) client = httpx.Client(timeout=timeout)
requests 只能设置整体超时秒数,无法区分连接和读/写阶段。
httpx 内置重试:
transport = httpx.HTTPTransport(retries=3) # 最多重试3次 client = httpx.Client(transport=transport)
requests 需要手动捕获异常并重试,或依赖第三方库如 requests-retry。
错误类型:httpx 提供了更丰富的异常层次(如 ConnectTimeout、ReadTimeout、RemoteProtocolError),便于针对不同错误类型做不同处理。
提问:那 httpx 的重试是智能的吗?429 状态码能重试吗?
答:httpx 的retries默认只对网络错误重试(如连接断开、超时),对 HTTP 状态码不自动重试,你需要配合Event Hooks或自定义传输层实现“按状态码重试”逻辑。
文件上传与流式响应
文件上传:httpx 支持更灵活的上传方式,包括分块上传、流式上传。
# 流式上传大文件
with open("bigfile.bin", "rb") as f:
response = client.post("https://example.com/upload", content=f)
requests 虽然也可以,但 httpx 的 content 参数支持迭代器,内存更友好。
流式响应下载:
# 逐块下载大文件
with client.stream("GET", "https://example.com/bigfile") as response:
for chunk in response.iter_bytes():
process(chunk)
requests 的 Response.iter_content(size) 同样支持,但 httpx 的 stream 上下文管理器更安全(自动处理连接释放)。
提问:流式响应是不是只适用于大文件?
答:还有实时数据流场景(如 SSE、WebSocket 升级),httpx 的stream模式与asyncio结合能清晰管理长连接。
常见问题问答
Q1:httpx 能完全替代 requests 吗?
A:在 90% 场景下可以,但如果你依赖 requests 的以下特性,需谨慎:
- requests-oauthlib(虽然 httpx 有
httpx_oauth但生态不成熟) - Session 的全局 cookie 自动管理(httpx 需要手动配置)
- 某些老旧代理配置(httpx 兼容性稍差)
Q2:httpx 的异步支持是否依赖特定异步框架?
A:httpx 基于 anyio,因此可配合 asyncio、trio 或 curio,无论你用 FastAPI(异步)还是普通脚本,都无缝集成。
Q3:httpx 的学习成本高吗?
A:API 设计高度模仿 requests,大部分函数名和参数相同,你只需要额外学习 async/await 语法和 Client 的配置方式,对于熟悉 requests 的开发者,迁移成本约 1-2 天。
Q4:性能上 httpx 能否每秒处理 10000 个请求?
A:高性能场景推荐使用 httpx.AsyncClient 配合连接池,理论上可突破 10k RPS(需注意 DNS 缓存和 TCP 端口耗尽),但实际瓶颈多在网络和服务器,而非客户端本身。
Q5:httpx 的社区活跃度和更新频率如何?
A:截至 2025 年,GitHub 上 httpx 有 14k+ star,每月更新 2-3 次,虽然不及 requests 的生态规模,但作为新生代库,已得到足够重视(如被 FastAPI 官方推荐作为测试客户端)。
我该升级到 HTTPX 吗?
| 你的场景 | 推荐选择 |
|---|---|
| 简单同步脚本,无并发 | requests(依赖少,代码经典) |
| 新项目,需异步/高并发 | HTTPX(原生支持,性能更好) |
| 需要 HTTP/2 支持 | HTTPX(唯一选择) |
| 需要精细连接池控制 | HTTPX(配置更灵活) |
| 依赖 requests 扩展生态 | requests(或考虑折中:同步用 requests,异步用 httpx) |
最终建议:如果你正在搭建一个现代 Python 项目(如基于 FastAPI 的微服务、高性能爬虫、API 网关),建议从开始就选择 HTTPX,它不仅性能更强、功能更现代,而且其“同步/异步双模式”能让你的代码在未来更容易扩展,不要被“习惯”束缚,HTTPX 才是 Python HTTP 客户端的未来方向。
注:本文基于 HTTPX 0.28 和 Requests 2.32 版本编写,特性可能随版本更新而变化。