warnings.filterwarnings 比 try/except 更合适,因为 UserWarning 不继承自 Exception,无法用 except Warning 捕获;它是 Python 警告系统的官方入口,支持按模块、消息正则、类别(须指定 UserWarning)精准控制。

UserWarning 默认不会中断程序,但反复出现会干扰调试和日志;用 warnings.filterwarnings 可精准控制——关键不是“全关”,而是按需抑制或重定向。
为什么 warnings.filterwarnings 比 try/except 更合适
因为 UserWarning 不是异常,它不触发 except Warning(Python 中 Warning 不继承自 Exception),所以不能用常规异常捕获。而 warnings.filterwarnings 是 Python 标准警告系统的官方入口,支持按模块、消息正则、警告类别精细匹配。
-
category参数必须设为UserWarning或其子类,写成Warning会覆盖所有警告(包括DeprecationWarning),容易掩盖真正该看的问题 - 作用域默认是全局的,但如果在函数内调用,需配合
reset=True或提前warnings.resetwarnings()避免污染其他模块 - 不加
module参数时,规则对所有导入模块生效;加了之后只影响指定模块(例如module="sklearn.*")
忽略特定 UserWarning 的三种常用写法
最常见需求是屏蔽某条重复提示,比如 pandas 的 SettingWithCopyWarning 或 numpy 的 RuntimeWarning: invalid value encountered in double_scalars(注意:后者其实是 RuntimeWarning,不是 UserWarning,别填错 category)。
- 按警告类型忽略:
warnings.filterwarnings("ignore", category=UserWarning) - 按消息文本忽略(推荐):
warnings.filterwarnings("ignore", message=".*divide by zero.*", category=RuntimeWarning)—— 正则要能匹配实际报出的完整提示字符串 - 按模块+类型组合:
warnings.filterwarnings("ignore", category=UserWarning, module="my_package\.utils")(注意反斜杠转义点号)
把 UserWarning 记录到日志而不是丢弃
生产环境不建议直接 ignore,更稳妥的是捕获后写入日志,便于后续审计。这需要搭配 warnings.catch_warnings 上下文管理器或自定义 showwarning 函数。
- 简单记录:在程序启动时设置
warnings.filterwarnings("always", category=UserWarning),再用logging.captureWarnings(True),这样所有警告会自动转成WARNING级日志 - 定制记录:重写
warnings.showwarning,例如:def custom_showwarning(message, category, filename, lineno, file=None, line=None): logging.warning(f"{category.__name__}: {message} ({filename}:{lineno})") warnings.showwarning = custom_showwarning - 注意:如果用了
logging.captureWarnings(True),就不要再手动改showwarning,否则会重复记录
真正难的不是怎么 suppress,而是判断哪条 warning 值得留、哪条该修——比如 FutureWarning 提示 API 即将废弃,DeprecationWarning 默认被静默,但它们比 UserWarning 更值得优先处理。忽略前最好先 python -W error::UserWarning script.py 把它当错误跑一次,看看是不是底层逻辑真有问题。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











