
当系统中安装了 zstandard 第三方库时,Requests 会自动在 Accept-Encoding 请求头中加入 zstd,导致服务器返回 zstd 压缩内容但未自动解压,引发乱码或解析失败。本文详解其机制并提供安全、全局、无需修改业务代码的禁用方案。
当系统中安装了 `zstandard` 第三方库时,requests 会自动在 `accept-encoding` 请求头中加入 `zstd`,导致服务器返回 zstd 压缩内容但未自动解压,引发乱码或解析失败。本文详解其机制并提供安全、全局、无需修改业务代码的禁用方案。
Requests 库本身不原生支持 zstd 解压缩——它仅在检测到 zstandard 模块可用时,单方面添加 zstd 到默认 Accept-Encoding 头中(如 'gzip, deflate, br, zstd'),却不会自动注册对应的解压处理器。这造成一个关键不对称:请求“声称能处理 zstd”,但响应体仍以原始 zstd 字节流形式返回(response.content 为乱码二进制),而 response.text 或 response.json() 因无法解压而失败。
这一行为源于 Requests 的自动编码协商机制,其逻辑如下:
# 简化示意(非实际源码)
if HAS_ZSTD:
default_accept_encodings.append('zstd')
其中 HAS_ZSTD 通过 import zstandard 是否成功判定。因此,禁用 zstd 支持最直接、最可靠的方式是卸载该模块:
pip uninstall zstandard
✅ 优势:
- 彻底移除触发条件,一劳永逸;
- 不影响其他压缩格式(gzip/deflate/br)的自动处理;
- 无兼容性风险,符合 Requests 官方设计预期。
⚠️ 注意事项:
-
若项目确实需要 zstd 压缩能力(如对接特定 API),则不应卸载,而应显式禁用编码协商:
import requests # 全局禁用 zstd(推荐于脚本开头执行) requests.utils.default_user_agent = lambda: "python-requests/2.32.0" # 并覆盖默认 Accept-Encoding from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry session = requests.Session() session.headers['Accept-Encoding'] = 'gzip, deflate, br' # 显式排除 zstd
切勿使用
verify=False或proxies={}等无关配置试图绕过——此问题与 SSL 或代理完全无关,属于请求头协商层面的逻辑。Synology DSM 7 系统更新后预装
zstandard是常见诱因。可通过pip list | grep zstandard确认,并优先采用pip uninstall zstandard解决,避免逐个修改数百行requests.get()调用。
总结:Requests 的 zstd 自动启用是“有头无尾”的半集成设计。对绝大多数用户而言,卸载 zstandard 是最简洁、最健壮的解决方案;若需保留该模块,则务必通过 session.headers 显式控制 Accept-Encoding,确保压缩声明与实际处理能力严格一致。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











