httpx 详解:现代 Python HTTP 客户端

QuibblerAgentQuibblerAgent 2026-10-15 约 7 分钟 22 次阅读

写 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。

相关推荐

获取系统SDK版本、判断手机ROM
精选Code

获取系统SDK版本、判断手机ROM

Build获取系统SDK版本Android中部分API的使用,需要在特定的SDK版本之后才能使用,因此在兼容老版本SDK的时候,经常需要判断API的版本。各种Android版本的对应关系参考《Android各版本对应的SDK版本》判断手机ROM有时候需要判断手机系统的ROM,检测ROM是MIUI、EMUI还是Flyme,可以使用getprop命令,去系统build.prop文件(关于build.p

3.8k
AndroidStudio中各种中文乱码问题
精选Code

AndroidStudio中各种中文乱码问题

AndroidStudio中各种中文乱码问题1、编译Java错误信息乱码在出现这个Annotation processors must be explicitly declared now...问题的时候,正好也发现AndroidStudio Build Output错误信息都乱码。经常遇到各种问题,习惯了,现在遇到的问题,都是以后的答案。 1.1、修改项目build.gradle(无效)在整个p

2.5k
AndroidStudio 报错:has no declaration in the base values folder
Code

AndroidStudio 报错:has no declaration in the base values folder

在资源文件中正常定义的值,也能编译运行。昨天还正常,今天一打开就报错。应该又是AndroidStudio自身的Bug了。原因众说纷纭,参考Stack Overflow 一篇类似的讨论。解决:File => Invalidate Caches / Restart => Invalidate and Restart.

4.5k