脚本功能一切正常,可每次运行都要先刷一行黄色警告,把真正的正常输出挤得看不见。命令行工具尤其难受:想看结果,得先拨开这行噪声。
现象
几乎每次运行脚本,输出开头都固定带着一行警告:
.../site-packages/requests/__init__.py:112: RequestsDependencyWarning:
urllib3 (2.x.x) or chardet (5.x.x)/charset_normalizer (3.x.x) doesn't match a supported version!
warnings.warn(...)
下面的业务输出就淹在这行下面。一行两行还好,对于那些要在循环里反复调用的脚本、或者被别的程序当子进程调用的场景,这行警告会不停地刷。
根因
RequestsDependencyWarning 是 requests 库发出的"依赖版本不匹配"提示。
requests 自己并不能独立完成所有事,它底层依赖几个库:HTTP 连接池(urllib3)、字符集探测(早期是 chardet,后来换成 charset_normalizer)等。requests 对这几个底层库的版本是有要求范围的。当环境中装着的版本落在范围之外——比如 urllib3 装得太新、或者 chardet 版本对不上——requests 在导入时检查到这一点,就会发出一条 RequestsDependencyWarning,意思是"我可能跟这些依赖配合得不好,你注意一下"。
它不报错、不中断,因为多数情况下确实还能凑合用。但它每次都提醒,因为每次导入 requests 都会做一次版本检查。
根本原因就是版本没对齐:要么是某个依赖被别的包连带升级/降级过,要么是安装了多个版本的同一依赖、命中的不是期望的那个。
解决
治本:把依赖版本对齐。 先看清楚现在各依赖装的什么版本,再按 requests 支持的版本范围调整:
python -m pip show requests urllib3 charset-normalizer chardet
然后按需要升级或降级到匹配的版本。最稳妥的方式是让 pip 自己解一遍依赖:
python -m pip install --upgrade --force-reinstall requests
pip 会根据 requests 的依赖约束,把 urllib3 等拉到兼容版本。(如果你有 pip-tools,用 pip-compile 生成一份锁定的依赖清单,更能保证版本组合稳定。)
装完再跑一次,警告应该消失。
应急:现场先把这类第三方噪声过滤掉。 在命令行层面,把 stderr 里含该警告的行滤掉:
python script.py 2>&1 | grep -v "RequestsDependencyWarning"
注意 2>&1 是把标准错误合进标准输出——警告是写到 stderr 的,不合并的话 grep 过滤不到。
更好一点的应急:在脚本里用 warnings 机制屏蔽。 针对性地忽略这一类警告,而不是把所有警告一刀切:
import warnings
warnings.filterwarnings(
"ignore",
message=".*doesn't match a supported version.*",
category=Warning,
)
切记不要用 warnings.filterwarnings("ignore") 全局静音——那会把你自己的代码可能发出的、真正有用的警告也一起堵死。
延伸与预防
一句总结:警告要在源头修,过滤只是临时止血。
过滤的价值在于"临时让输出干净一点",让排查不被干扰;但它并没有解决版本不匹配,库与库之间的兼容风险仍然存在。所以正确的顺序是:先用过滤让自己能看清输出、定位到底哪个依赖对不上,然后回到版本层面把它修掉。
预防上:
- 锁定依赖版本。 项目里维护
requirements.txt(或pyproject.toml/poetry.lock/pip-compile产物),把requests、urllib3、charset_normalizer这些"有版本约束"的库都固定住。避免某次pip install 别的东西顺手把它们改掉。 - 别在系统 Python 里堆依赖。 用虚拟环境隔离每个项目,不同项目对同一库的版本要求就不会打架。
- 把警告当信号,别当噪声。
warnings.warn是库作者在明确告诉你"这里可能有问题"。合理的态度是:看一眼、判断要不要处理;要处理就修根因,确实无关紧要就精确地忽略它,而不是习惯性地全局静音。 - 在 CI 里让警告变显式。 可以在测试时加上
-W error,把警告提升为错误,逼自己和团队正视它们——这比让警告在日志里烂掉要健康得多。