httpx 是一个功能强大且现代化的 Python HTTP 客户端库,支持同步和异步请求,并兼容 requests API。除基础请求外,它还提供 HTTP/2、连接池、细粒度超时控制、代理、认证、流式响应以及实验性 WebSocket 等能力。本文围绕 httpx 的安装、核心特性、同步/异步用法、高级配置、异常处理以及与 requests 的差异进行整理,适合需要在脚本、爬虫、后端服务或自动化任务中落地 HTTP 请求的开发者参考。
一、安装 httpx
- pip install httpx
- 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. 同步请求
快捷方式适合简单请求:
- import httpx
- response = httpx.get('https://httpbin.org/get')
- print(response.status_code) # 200
- print(response.json()) # 解析 JSON 响应
复制代码
如果要复用连接,推荐使用 Client:
- import httpx
- with httpx.Client() as client:
- response = client.get('https://httpbin.org/get')
- 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 语法,适合高并发场景:
- import asyncio
- import httpx
- async def fetch():
- async with httpx.AsyncClient() as client:
- response = await client.get('https://httpbin.org/get')
- print(response.json())
- asyncio.run(fetch())
复制代码
如果要在异步环境中并发多个请求,可以用 asyncio.gather:
- import asyncio
- import httpx
- async def main():
- urls = ['https://httpbin.org/get'] * 5
- async with httpx.AsyncClient() as client:
- tasks = [client.get(url) for url in urls]
- responses = await asyncio.gather(*tasks)
- for resp in responses:
- print(resp.status_code)
- asyncio.run(main())
复制代码
四、高级配置
1. 超时设置
可以针对单个请求设置超时,单位是秒:
- import httpx
- response = httpx.get('https://httpbin.org/delay/2', timeout=5.0)
复制代码
也可以细粒度控制连接、读取、写入和连接池超时:
- import httpx
- timeout = httpx.Timeout(connect=5, read=10, write=2, pool=1)
- response = httpx.get('https://httpbin.org/delay/2', timeout=timeout)
- with httpx.Client(timeout=timeout) as client:
- client.get('https://httpbin.org/delay/2')
复制代码
其中 connect 是连接超时,read 是读取超时,write 是写入超时,pool 是连接池获取超时。
2. 请求头与查询参数
headers 传字典,params 传字典,params 会被自动编码:
- import httpx
- headers = {'User-Agent': 'my-app/1.0'}
- params = {'key1': 'value1', 'key2': 'value2'}
- response = httpx.get(
- 'https://httpbin.org/get',
- headers=headers,
- params=params
- )
- # 实际请求 URL:
- # https://httpbin.org/get?key1=value1&key2=value2
复制代码
3. POST 表单与 JSON
表单数据用 data 参数,JSON 数据用 json 参数。json 参数会自动序列化并设置 Content-Type: application/json:
- import httpx
- data = {'username': 'test', 'password': '123'}
- response = httpx.post('https://httpbin.org/post', data=data)
- json_data = {'name': 'Alice', 'age': 30}
- response = httpx.post('https://httpbin.org/post', json=json_data)
复制代码
4. 文件上传
files 参数可以传单文件或多文件。单文件上传:
- import httpx
- with open('file.txt', 'rb') as f:
- files = {'file': ('file.txt', f, 'text/plain')}
- response = httpx.post('https://httpbin.org/post', files=files)
复制代码
多文件上传:
- import httpx
- files = [
- ('images', ('img1.jpg', open('img1.jpg', 'rb'), 'image/jpeg')),
- ('images', ('img2.png', open('img2.png', 'rb'), 'image/png'))
- ]
- response = httpx.post('https://httpbin.org/post', files=files)
复制代码
files 中元组的含义是:字段名、文件名、文件对象和 MIME 类型。
5. 代理设置
httpx 支持 HTTP、HTTPS、SOCKS 代理:
- import httpx
- proxies = {
- 'http://': 'http://user:pass@proxy:8080',
- 'https://': 'https://user:pass@proxy:443',
- 'all://': 'socks5://user:pass@socks-proxy:1080'
- }
- client = httpx.Client(proxies=proxies)
- response = httpx.get('https://httpbin.org/ip', proxies=proxies)
复制代码
其中 all:// 表示所有协议都走 SOCKS5 代理。
6. 认证
httpx 支持 Basic、Digest、OAuth 等认证方式。Basic 认证示例:
- import httpx
- from httpx import BasicAuth
- auth = BasicAuth(username='user', password='pass')
- response = httpx.get('https://httpbin.org/basic-auth/user/pass', auth=auth)
- # 也可以直接传元组,自动识别为 BasicAuth
- response = httpx.get('https://httpbin.org/basic-auth/user/pass', auth=('user', 'pass'))
复制代码
7. 流式响应
处理大文件下载时,可以通过流式读取避免一次性加载到内存:
- import httpx
- with httpx.stream('GET', 'https://httpbin.org/stream/20') as response:
- for chunk in response.iter_bytes(chunk_size=1024):
- print(len(chunk))
复制代码
iter_bytes 会按 chunk_size 逐块读取,适合边下载边写入文件或做实时处理。
五、异常处理
httpx 定义了多个异常类,实际开发中应捕获特定异常,而不是直接捕获通用 Exception。常见异常如下:
httpx.RequestError:网络层错误,例如 DNS 失败、连接拒绝。
httpx.HTTPStatusError:响应状态码非 2xx,需要手动触发。
httpx.TimeoutException:超时错误。
httpx.ConnectError:连接错误。
httpx.ReadError:读取响应错误。
示例:
- import httpx
- try:
- response = httpx.get('https://httpbin.org/status/404')
- response.raise_for_status()
- except httpx.HTTPStatusError as e:
- print(f'HTTP 错误: {e.response.status_code}')
- except httpx.RequestError as e:
- print(f'请求错误: {e}')
- except httpx.TimeoutException:
- 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 仍然足够稳定。 |