Python HTTP 客户端
用标准库 urllib 与生态库 requests/httpx 发起 HTTP;超时、错误与会话是工程关键。
#concept
#growing
#dev
#python
#python
[!info] related notes
Python HTTP 客户端
这个概念为什么出现
服务集成几乎总是 HTTP。不设超时的客户端会在故障时拖垮线程/协程池。
[!abstract] 一句话理解 HTTP 客户端负责请求构建、超时、状态码处理与连接复用;标准库可用,工程上常用 requests/httpx。
最小可运行示例
场景:用标准库 GET 示例(无外网时可本地跳过)
# urllib_get_demo.py
# 业务意图:演示标准库 GET 与超时参数形态。
# 教学点:Request/urlopen;超时;状态。
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen
def fetch(url: str, timeout_s: float = 3.0) -> int:
req = Request(url, headers={"User-Agent": "thought-forest-demo"})
with urlopen(req, timeout=timeout_s) as resp:
return resp.status
def main() -> None:
try:
code = fetch("https://example.com")
print("status:", code)
except HTTPError as exc:
# HTTPError 也是 URLError,先处理已收到的 HTTP 错误响应。
print("http error:", exc.code)
exc.close()
except (URLError, TimeoutError) as exc:
print("network error:", type(exc).__name__)
if __name__ == "__main__":
main()
建议运行:
python urllib_get_demo.py
可能输出 status: 200、http error: ... 或 network error: ...,取决于响应与网络。此函数仅取得状态,不消费响应 body。
结合场景再看三个关注点
- urllib 的 timeout 约束底层阻塞操作,不是整个请求的总时限;多次读写、DNS 等阶段不能简单视为共享一个完整 deadline。
- 生产 JSON API 常用 session。
- 异步栈考虑 httpx/aiohttp。
核心概念与准确模型
| 库 | 特点 |
|---|---|
| urllib | 标准库,API 偏底层 |
| requests | 同步生态事实标准之一 |
| httpx | 同步与异步 API |
- 幂等重试要谨慎
- urllib 对未处理的 HTTP 错误抛 HTTPError;requests/httpx 通常须调用
raise_for_status()才把错误状态转换为异常。
边界情况与反直觉行为
- 重定向与 SSRF
- 流式下载需限制累计大小并关闭响应;read timeout 通常限制等待数据的间隔,持续缓慢到达的数据仍可能让总时长很长。
- 代理与证书
常见误区
[!warning] 常见误区:不设超时 错误理解:默认永远返回。
正确模型:默认必须有超时预算。
工程实践
- 统一 client 封装
- 日志 correlation id
- 重试同时考虑操作幂等性、请求体能否重放、失败阶段与总预算;超时并不证明服务端尚未执行。
本节总结
客户端是可靠性边界。超时、错误分类与会话管理优先于“能请求就行”。
自测题
- 为何要超时?
- 5xx 与连接错误差别?
参考答案
- 防止故障传播与资源占死。
- 前者有 HTTP 响应,后者可能未完成传输。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| urllib.request | 文档 | 标准库 |
| HTTPX | 文档 | 现代客户端 |