写 Python 的 HTTP 调用时,requests 几乎是肌肉记忆,但它的同步模型与缺失的 HTTP/2 支持在异步时代越来越显得吃力。httpx 自称"新一代 Python HTTP 客户端"(A next-generation HTTP client for Python),由 encode 团队维护,GitHub 上约 14k Star,BSD 协议开源。本文从它的定位与特性讲起,给出同步与异步两套上手代码,再展开客户端对象、高级特性,最后与 requests 做一次认真的选型对比。
1、项目概述
httpx 的一句核心卖点是:requests 兼容的 API,加上现代网络栈缺的那几块。它要求 Python 3.9 及以上,核心依赖只有 httpcore、certifi、idna、snio 四个,可选依赖覆盖 h2、socksio、brotli 等扩展能力。
官方列出的特性清单相当扎实。
- 与 requests 兼容的请求 API,迁移成本接近零
- 同时提供同步接口与异步接口
- HTTP/1.1 与 HTTP/2 双协议支持
- 可直接请求 WSGI / ASGI 应用,测试无需起端口
- 严格超时默认值、完整类型注解、100% 测试覆盖率
安装按需选择附加项即可。
pip install httpx
如需 HTTP/2,换成 pip install httpx[http2];想装一个类似 httpie 的命令行客户端,则用 pip install 'httpx[cli]'。
2、快速上手
最简用法与 requests 逐字级一致,README 的开篇示例就是最好的证明。
>>> import httpx
>>> r = httpx.get('https://www.example.org/')
>>> r
<Response [200 OK]>
>>> r.status_code
200
>>> r.headers['content-type']
'text/html; charset=UTF-8'
httpx.get 是模块级快捷函数,返回的 Response 对象拥有 status_code、headers、text、json() 等熟悉的属性方法。从 requests 迁移过来的代码,多数只需要把 import requests 换成 import httpx。
真正拉开差距的是异步支持。同一套 API 镜像出 AsyncClient,在 asyncio 事件循环里并发请求毫无压力。
import asyncio
import httpx
async def main():
async with httpx.AsyncClient() as client:
r = await client.get("https://www.example.org/")
print(r.status_code)
asyncio.run(main())
注意模块级 httpx.get 每次都会新建连接,而 Client / AsyncClient 上下文管理器会复用连接池——生产代码里应始终用后者,这也是官方文档反复强调的实践。
3、客户端对象与超时控制
httpx.Client 是生产环境的标准姿势:连接池、Cookie 持久化、跨请求的公共配置都挂在它身上。
with httpx.Client(
base_url="https://api.example.com",
timeout=5.0,
headers={"Authorization": "Bearer token"},
) as client:
r = client.get("/users")
r.raise_for_status()
base_url 让路径写法保持干净,raise_for_status() 在非 2xx 时抛异常,这两个组合能覆盖绝大多数接口调用的样板逻辑。
超时是 httpx 比 requests 做得更严谨的地方:默认 5 秒超时而非无限等待,且可以用 httpx.Timeout(connect=2.0, read=10.0) 细分连接、读取、写入、池化四个阶段。爬虫或网关场景里,"默认就安全"这一条足以成为换库理由。
4、高级特性速览
- HTTP/2:装上
httpx[http2]后Client(http2=True)即启用,对支持 h2 的源站可多路复用 - 代理:
proxies=参数兼容 http 与 socks 代理(socks 需socksio) - 流式下载:
client.stream("GET", url)上下文里逐块读取,大文件不占内存 - WSGI/ASGI 直连:
Client(app=app)把请求直接递给本地框架,测试 FastRequest、Flask 应用无需真实网络 - multipart 上传、自动解压、自动编码探测等 requests 标配能力全部继承
其中 WSGI/ASGI 直连对测试的价值最被低估:集成测试里既不需要 mock 掉传输层,也不需要占用端口号启动服务器,速度与确定性兼得。
5、与 requests 选型对比
| 维度 | httpx | requests |
|---|---|---|
| 异步支持 | 原生 AsyncClient | 无 |
| HTTP/2 | 可选启用 | 不支持 |
| 默认超时 | 5 秒 | 无限 |
| 生态存量 | 增长中 | 无处不在 |
选型建议按场景切分:新项目尤其涉及 asyncio、FastAPI 的,直接 httpx,同构的同步异步 API 让你两套代码共享心智模型;存量 requests 代码运行良好且无异步需求,不必为了换而换——两边 API 兼容,真要迁移也只是逐步替换 import 的节奏。另外许多新框架(如 FastAPI 的 TestClient)底层就是 httpx,学会它等于顺带掌握了这套测试设施。
6、总结
httpx 用 requests 级的易用性补齐了异步、HTTP/2、严格超时与 ASGI 测试这几块现代 Python 网络栈的短板,类型注解与全覆盖测试也让它在 IDE 体验和可维护性上更配得上 2026 年的工程标准。对于启动新服务的后端工程师,建议从第一天就用 AsyncClient 加显式超时;对于维护存量代码的团队,建议在新增模块里先行试点、利用 API 兼容性渐进迁移。项目地址:encode/httpx,文档见 www.python-httpx.org。

