查看: 230|回复: 0

Python httpx同步异步请求与HTTP/2客户端开发指南

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
httpx 是一个功能强大且现代化的 Python HTTP 客户端库,支持同步和异步请求,并兼容 requests API。除基础请求外,它还提供 HTTP/2、连接池、细粒度超时控制、代理、认证、流式响应以及实验性 WebSocket 等能力。本文围绕 httpx 的安装、核心特性、同步/异步用法、高级配置、异常处理以及与 requests 的差异进行整理,适合需要在脚本、爬虫、后端服务或自动化任务中落地 HTTP 请求的开发者参考。

一、安装 httpx
  1. pip install httpx
  2. pip install httpx[http2]
复制代码

第一条命令安装 httpx;如果需要 HTTP/2 支持,需要额外安装依赖。

二、核心特性

1. 同步与异步双模式:同步使用 httpx,异步使用 AsyncClient。
2. HTTP/2 支持:默认优先使用 HTTP/2,但需要服务端支持。
3. 类型提示:完善的类型注解,提升代码可读性和 IDE 支持。
4. 连接池:复用 TCP 连接,减少握手开销。
5. 超时控制:细粒度设置连接、读取、写入超时。
6. 代理与认证:支持 HTTP/HTTPS/SOCKS 代理,以及 Basic/Digest/OAuth 认证。
7. 流式请求/响应:适合大文件上传和下载。
8. WebSocket 支持:实验性支持 WebSocket 协议。

三、基本用法

1. 同步请求

快捷方式适合简单请求:
  1. import httpx
  2. response = httpx.get('https://httpbin.org/get')
  3. print(response.status_code)  # 200
  4. print(response.json())       # 解析 JSON 响应
复制代码

如果要复用连接,推荐使用 Client:
  1. import httpx
  2. with httpx.Client() as client:
  3.     response = client.get('https://httpbin.org/get')
  4.     print(response.text)
复制代码

常用方法包括:
get(url, params=...):GET 请求。
post(url, data=..., json=...):POST 请求,data 传表单,json 传 JSON。
put()、delete()、patch():其他请求方法。
head()、options():HEAD 和 OPTIONS 请求。

2. 异步请求

异步请求需要配合 async/await 语法,适合高并发场景:
  1. import asyncio
  2. import httpx
  3. async def fetch():
  4.     async with httpx.AsyncClient() as client:
  5.         response = await client.get('https://httpbin.org/get')
  6.         print(response.json())
  7. asyncio.run(fetch())
复制代码

如果要在异步环境中并发多个请求,可以用 asyncio.gather:
  1. import asyncio
  2. import httpx
  3. async def main():
  4.     urls = ['https://httpbin.org/get'] * 5
  5.     async with httpx.AsyncClient() as client:
  6.         tasks = [client.get(url) for url in urls]
  7.         responses = await asyncio.gather(*tasks)
  8.         for resp in responses:
  9.             print(resp.status_code)
  10. asyncio.run(main())
复制代码

四、高级配置

1. 超时设置

可以针对单个请求设置超时,单位是秒:
  1. import httpx
  2. response = httpx.get('https://httpbin.org/delay/2', timeout=5.0)
复制代码

也可以细粒度控制连接、读取、写入和连接池超时:
  1. import httpx
  2. timeout = httpx.Timeout(connect=5, read=10, write=2, pool=1)
  3. response = httpx.get('https://httpbin.org/delay/2', timeout=timeout)
  4. with httpx.Client(timeout=timeout) as client:
  5.     client.get('https://httpbin.org/delay/2')
复制代码

其中 connect 是连接超时,read 是读取超时,write 是写入超时,pool 是连接池获取超时。

2. 请求头与查询参数

headers 传字典,params 传字典,params 会被自动编码:
  1. import httpx
  2. headers = {'User-Agent': 'my-app/1.0'}
  3. params = {'key1': 'value1', 'key2': 'value2'}
  4. response = httpx.get(
  5.     'https://httpbin.org/get',
  6.     headers=headers,
  7.     params=params
  8. )
  9. # 实际请求 URL:
  10. # https://httpbin.org/get?key1=value1&key2=value2
复制代码

3. POST 表单与 JSON

表单数据用 data 参数,JSON 数据用 json 参数。json 参数会自动序列化并设置 Content-Type: application/json:
  1. import httpx
  2. data = {'username': 'test', 'password': '123'}
  3. response = httpx.post('https://httpbin.org/post', data=data)
  4. json_data = {'name': 'Alice', 'age': 30}
  5. response = httpx.post('https://httpbin.org/post', json=json_data)
复制代码

4. 文件上传

files 参数可以传单文件或多文件。单文件上传:
  1. import httpx
  2. with open('file.txt', 'rb') as f:
  3.     files = {'file': ('file.txt', f, 'text/plain')}
  4.     response = httpx.post('https://httpbin.org/post', files=files)
复制代码

多文件上传:
  1. import httpx
  2. files = [
  3.     ('images', ('img1.jpg', open('img1.jpg', 'rb'), 'image/jpeg')),
  4.     ('images', ('img2.png', open('img2.png', 'rb'), 'image/png'))
  5. ]
  6. response = httpx.post('https://httpbin.org/post', files=files)
复制代码

files 中元组的含义是:字段名、文件名、文件对象和 MIME 类型。

5. 代理设置

httpx 支持 HTTP、HTTPS、SOCKS 代理:
  1. import httpx
  2. proxies = {
  3.     'http://': 'http://user:pass@proxy:8080',
  4.     'https://': 'https://user:pass@proxy:443',
  5.     'all://': 'socks5://user:pass@socks-proxy:1080'
  6. }
  7. client = httpx.Client(proxies=proxies)
  8. response = httpx.get('https://httpbin.org/ip', proxies=proxies)
复制代码

其中 all:// 表示所有协议都走 SOCKS5 代理。

6. 认证

httpx 支持 Basic、Digest、OAuth 等认证方式。Basic 认证示例:
  1. import httpx
  2. from httpx import BasicAuth
  3. auth = BasicAuth(username='user', password='pass')
  4. response = httpx.get('https://httpbin.org/basic-auth/user/pass', auth=auth)
  5. # 也可以直接传元组,自动识别为 BasicAuth
  6. response = httpx.get('https://httpbin.org/basic-auth/user/pass', auth=('user', 'pass'))
复制代码

7. 流式响应

处理大文件下载时,可以通过流式读取避免一次性加载到内存:
  1. import httpx
  2. with httpx.stream('GET', 'https://httpbin.org/stream/20') as response:
  3.     for chunk in response.iter_bytes(chunk_size=1024):
  4.         print(len(chunk))
复制代码

iter_bytes 会按 chunk_size 逐块读取,适合边下载边写入文件或做实时处理。

五、异常处理

httpx 定义了多个异常类,实际开发中应捕获特定异常,而不是直接捕获通用 Exception。常见异常如下:
httpx.RequestError:网络层错误,例如 DNS 失败、连接拒绝。
httpx.HTTPStatusError:响应状态码非 2xx,需要手动触发。
httpx.TimeoutException:超时错误。
httpx.ConnectError:连接错误。
httpx.ReadError:读取响应错误。

示例:
  1. import httpx
  2. try:
  3.     response = httpx.get('https://httpbin.org/status/404')
  4.     response.raise_for_status()
  5. except httpx.HTTPStatusError as e:
  6.     print(f'HTTP 错误: {e.response.status_code}')
  7. except httpx.RequestError as e:
  8.     print(f'请求错误: {e}')
  9. except httpx.TimeoutException:
  10.     print('请求超时')
复制代码

这里的 raise_for_status() 会在状态码非 2xx 时抛出 HTTPStatusError。排查时可以先区分是网络层错误、连接错误、读取错误还是超时,再针对代理、DNS、服务端响应和超时参数逐项检查。

六、与 requests 对比

异步支持:requests 不支持,httpx 原生支持 AsyncClient。
HTTP/2 支持:requests 不支持,httpx 支持,但需要安装依赖。
连接池:requests 有基础支持,httpx 提供更高效的连接池管理。
类型提示:requests 有限,httpx 更完善。
WebSocket:requests 不支持,httpx 为实验性支持。

七、总结

httpx 可以看作 requests 的现代替代品,尤其适合需要异步、HTTP/2 或更高性能的场景。它的 API 设计与 requests 兼容,学习成本较低,同时提供更强大的扩展能力。对于新项目,可以优先考虑 httpx;如果只是简单同步请求,并且不需要 HTTP/2,requests 仍然足够稳定。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-10 12:20 , Processed in 0.032357 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部