httpx不能直接替代requests做异步调用,必须使用AsyncClient配合async/await,显式管理生命周期,避免混用同步接口阻塞事件循环。

httpx 完全可以替代 requests 做异步 HTTP 调用,但不能直接把 requests.get() 换成 httpx.get() 就完事——同步和异步 API 是两套独立接口,混用会阻塞事件循环或抛出 RuntimeError: no running event loop。
async/await 必须显式使用,不能“自动升级”
httpx 的异步能力依赖 Python 的 async/await 语法,所有异步方法(如 httpx.AsyncClient.get())必须在 async def 函数内调用,并用 await 等待。直接在普通函数里调用会报错或退化为同步行为。
-
httpx.get()和httpx.post()是同步接口,底层用的是线程池,和requests行为一致,不走 asyncio - 真正异步的是
httpx.AsyncClient实例的方法:比如client.get()、client.post() - 必须搭配
async with httpx.AsyncClient() as client:使用,否则连接池未正确关闭
AsyncClient 需要显式生命周期管理
不像 requests 每次调用都新建连接,httpx.AsyncClient 是长生命周期对象,复用连接池和 DNS 缓存。错误写法是每次请求都 new 一个 client,这会绕过连接复用,还可能耗尽文件描述符。
- 推荐在应用启动时创建单个
AsyncClient实例(例如 FastAPI 的 dependency 或全局变量) - 短生命周期场景(如脚本)必须用
async with包裹,确保__aexit__关闭连接 - 不要在
async def外部调用client.get(),那会触发RuntimeError: no current event loop
超时、重试、SSL 配置与 requests 不完全兼容
httpx 的超时模型更细粒度,默认超时是 timeout=5.0(总超时),而 requests 默认不设 timeout;重试需手动集成 httpx.AsyncHTTPTransport 或第三方库如 tenacity;SSL 验证默认开启,但自签名证书需显式传 verify=False 或指定 cert。
立即学习“Python免费学习笔记(深入)”;
- 超时可拆分为
connect、read、write、pool四部分,例如timeout=httpx.Timeout(10.0, connect=3.0) - 重试不是内置功能,
httpx.AsyncClient不提供retry参数,得自己 wrap 或用tenacity装饰await client.get(...) -
verify=False在异步 client 中生效,但会发出InsecureRequestWarning,生产环境应配cert或信任 CA
混合同步/异步调用容易掉坑
一个常见误区是:在异步函数里混用 requests.get() 或 httpx.get()。它们会阻塞整个协程,拖慢并发吞吐量。尤其在 FastAPI 或 Quart 中,这种写法会让高并发请求排队等待。
- 如果必须调用同步库(如某些 SDK),用
asyncio.to_thread()(Python 3.9+)或loop.run_in_executor()包装 - 不要在
AsyncClient实例上调用.get()以外的同步方法(比如.build_request()返回的是同步 Request 对象) - 日志、JSON 解析等 CPU 密集操作建议用
asyncio.to_thread(json.loads, text)避免阻塞事件循环
最常被忽略的其实是连接池复用和事件循环绑定——很多人写了 async def,却忘了 await,或者把 AsyncClient 实例存在类属性里但没做并发安全处理。异步不是加个 async 就能跑,它要求整条调用链都适配。
文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/jiquanzatan/127177.html