返回专题首页

Python 专题

发起一次可靠请求:requests、httpx 与接口调用实践

网络请求几乎是所有 Python 项目的基础动作之一,无论你是在写爬虫、脚本、自动化任务,还是 Web 服务,最终都要面对超时、失败、重试、连接复用和错误处理这些现实问题。

Python 专题第 30 篇 / 39 篇4 分钟

网络请求几乎是所有 Python 项目的基础动作之一,无论你是在写爬虫、脚本、自动化任务,还是 Web 服务,最终都要面对超时、失败、重试、连接复用和错误处理这些现实问题。

这一节我们会从最常见的 requests 讲起,再扩展到支持异步能力的 httpx,重点不只是会发请求,而是学会如何把请求写得更可靠、更适合进入项目。

从一次最简单的 HTTP 请求开始

最简单的请求当然不复杂:

import requests

response = requests.get("https://example.com")
print(response.text)

但真实世界里的请求很快就会超出“拿到文本”这么简单。你通常还要关心:

  • 状态码是不是成功;
  • 会不会超时;
  • 返回内容是不是期望格式;
  • 失败时是否要重试;
  • 这段逻辑要不要统一封装。

所以“会发请求”和“会写请求层”之间,其实隔着一整套稳定性设计。

requests:同步调用的主流选择

requests 之所以流行,很大程度上是因为它 API 友好、心智直接,非常适合同步脚本和普通阻塞式业务。

对于很多自动化脚本、后台任务或中小规模服务来说,只要不是高并发异步链路,requests 依然是很自然的选择。

不过它的优势也意味着边界很明确:它主要是同步模型。如果你的项目核心已经是异步链路,再硬塞 requests 进去,就会破坏整体调度方式。

httpx:兼顾同步与异步

httpx 的价值,在于它同时覆盖同步和异步使用场景,而且接口风格和 requests 有一定延续性。

这让它特别适合:

  • 未来可能从同步过渡到异步的项目;
  • 已经基于 asyncio 或异步框架的服务;
  • 希望统一客户端抽象的团队。

所以 httpx 不只是“另一个请求库”,它更像是在现代 Python 工程里把请求能力和异步模型接得更顺的一种选择。

超时、重试与连接复用

真正可靠的请求层,至少要把这三件事想清楚。

第一是超时。没有超时的请求,本质上就是把系统命运交给对方服务。只要对方卡住,你这边就可能一直挂起。

第二是重试。重试不是越多越好,而是要区分哪些错误是短暂性波动,哪些错误重试也没有意义。

第三是连接复用。如果每次请求都重新建连接,性能和资源消耗都会比较差。会话级客户端或连接池机制能显著改善这件事。

这说明请求稳定性从来不是一个 get() 调用能解决的,而是围绕超时、失败策略和资源复用形成的一整套边界设计。

如何封装一个更可靠的请求层?

很多项目初期会直接在业务里到处写请求代码,但一旦接口变多、鉴权变复杂、日志和异常处理需要统一,散落调用就会变得很难维护。

更稳妥的做法通常是封装一层请求客户端,统一处理:

  • 基础地址;
  • 认证头;
  • 超时设置;
  • 状态码检查;
  • 错误转换;
  • 必要的日志。

这样业务层面对的就不再是一个裸 HTTP 库,而是一个更贴近项目语义的调用接口。

请求失败后应该如何处理?

请求失败不应该只有一个“抛异常然后算了”的粗糙策略。

你至少要区分:

  • 网络层失败;
  • 对方返回非 2xx 状态;
  • 返回数据格式不合法;
  • 业务语义错误。

不同失败类型,对应的处理方式往往不同。有的适合重试,有的适合直接上抛,有的要包装成统一业务异常,有的则要给上层更友好的错误说明。

所以请求层设计成熟与否,很多时候看的是它如何面对失败,而不是如何面对成功。

总结与预告

这一节我们把“会发请求”和“会写可靠请求”区分开了。请求层真正重要的从来不是调用某个 API,而是超时、重试、错误处理和封装边界这些决定稳定性的细节。

接下来我们会把前面的语言与工程能力带进 FastAPI,开始正式进入 Python Web 后端的框架实践阶段。