直接 try/except 无法捕获 Warning,因为 Warning 继承自 BaseException 而非 Exception;必须用 warnings.simplefilter("error") 或 warnings.filterwarnings("error", ...) 将其升级为异常才能捕获。

Warning 默认不会中断程序,但如果你需要强制捕获并处理(比如 CI 中禁止任何警告),必须主动提升为异常,不能只靠 try/except 捕获 —— 因为 Warning 不是 Exception 的子类。
为什么直接 try/except 无法捕获 Warning
Python 的 Warning 类型继承自 BaseException 但**不继承 Exception**,所以常规异常捕获机制对它无效。运行时看到的黄色提示只是被 warnings 模块默认打印出来,并未抛出可捕获的异常。
- 典型现象:
DeprecationWarning、UserWarning出现后程序继续执行,except Warning:根本不触发 - 根本原因:警告不是异常,除非你显式调用
warnings.warn()并配合过滤规则“升级”为异常 - 关键动作:必须通过
warnings.simplefilter("error")或更细粒度的warnings.filterwarnings("error", ...)改变警告行为
使用 simplefilter 将所有 Warning 转为异常
warnings.simplefilter("error") 是最简方式,它让所有未被其他规则覆盖的警告都变成 Warning 类异常(实际是 Warning 的子类,如 DeprecationWarning),从而可被 try/except 捕获。
import warnings
<p>warnings.simplefilter("error")</p><p>try:
warnings.warn("This will now raise an exception", UserWarning)
except UserWarning as e:
print(f"Caught: {e}")
</p>
- 适用场景:单元测试、CI 流水线中“零警告”策略,或快速验证某段代码是否引入废弃 API
- 注意点:
simplefilter是全局生效的,会影响后续所有模块(包括第三方库),建议在测试上下文中用with warnings.catch_warnings():配合使用 - 风险:若依赖的库内部触发了
FutureWarning等,可能意外中断,需结合具体警告类型过滤
按类型/模块精准过滤并提升为异常
粗暴地把所有警告转异常容易误伤,更稳妥的做法是只针对特定警告类型、来源模块或消息内容升级。这时要用 warnings.filterwarnings("error", ...)。
import warnings
<h1>只将当前模块中的 DeprecationWarning 升级为异常</h1><p>warnings.filterwarnings("error", category=DeprecationWarning, module=<strong>name</strong>)</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill6933" title="python-script-generator"><img
src="https://img.php.cn/upload/skill/000/000/081/179119443150703.jpg" alt="python-script-generator" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill6933" title="python-script-generator" class="overflowclass">python-script-generator</a>
<p class="overflowclass">快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。</p>
</div>
<a rel="nofollow" href="/xiazai/skill6933" title="python-script-generator" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><h1>或匹配警告消息中的关键词(正则)</h1><p>warnings.filterwarnings("error", message=".<em>invalid escape.</em>", category=SyntaxWarning)</p><h1>注意:module 参数匹配的是触发警告的模块名,不是当前文件名;<strong>name</strong> 在脚本中为 "<strong>main</strong>"</h1><p></p>
- 常用参数:
category(警告类)、message(正则字符串)、module(模块名)、lineno(行号) - 优先级:后注册的规则优先级更高;
simplefilter设置的规则可被后续filterwarnings覆盖 - 调试技巧:加
action="always"+print先确认警告真实触发位置和类型,再决定如何 filter
在测试中安全启用警告异常化
避免污染全局状态,推荐在测试函数内用 warnings.catch_warnings(record=True) 或临时重置过滤器。
import warnings
import pytest
<p>def test_no_deprecation():
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("error", DeprecationWarning)</p><h1>执行待测代码</h1><pre class="brush:php;toolbar:false;"> some_legacy_function()
# 若没抛异常,说明没触发 DeprecationWarning
assert len(w) == 0
-
catch_warnings(record=True)会捕获警告对象列表,适合断言数量或内容,但不会自动转异常 - 真正要“中断+捕获”,仍需配合
simplefilter("error")或filterwarnings("error") - pytest 自带
pytest.warns(),但那是验证警告是否发生,不是让它中断 —— 需求不同,别混用
真正难的不是怎么写那行 simplefilter,而是判断哪些警告该升级、哪些该忽略、哪些其实暴露了底层逻辑缺陷。比如 ResourceWarning 在测试中常被忽略,但它在生产环境可能预示连接泄漏 —— 这时候“转异常”反而是最轻量的兜底手段。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










