不懂就查#1:为什么Warning是这样的?

1,088 阅读4分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情

不懂就查系列是基于兴趣的系列
起因是小小的强迫症,看到异常之类的东西喜欢去究其原因,算是给自己解惑
本文内容是基于网络平台提供的知识点,感谢互联网和那些愿意分享知识的大佬们
希望能坚持下去

问题的起因

好奇

在本人开始学习某些东西的时候,配置环境成功的当天,在控制台看到了这个

C:\Users\10694\AppData\Local\Programs\Python\Python39\lib\site-packages\mmcv\__init__.py:20: UserWarning: On January 1, 2023, MMCV will release v2.0.0, in which it will remove components related to the training process and add a data transformation module. In addition, it will rename the package names mmcv to mmcv-lite and mmcv-full to mmcv. See https://github.com/open-mmlab/mmcv/blob/master/docs/en/compatibility.md for more details.
  warnings.warn(

P.S:这个警告是因为程序所使用的软件库即将更换包名,对库的引用会有影响

强迫症发作,点进文档,发现了这段警告如下所示

warnings.warn(
    'On January 1, 2023, MMCV will release v2.0.0, in which it will remove '
    'components related to the training process and add a data transformation '
    'module. In addition, it will rename the package names mmcv to mmcv-lite '
    'and mmcv-full to mmcv. '
    'See https://github.com/open-mmlab/mmcv/blob/master/docs/en/compatibility.md '
    'for more details.')

顺便附上方法内部(因为不会继续去查底层,所以没有继续从源代码查找了)

def warn(*args, **kwargs): # real signature unknown
    """ Issue a warning, or maybe ignore it or raise an exception. """
    pass

理解控制台为什么出现那行命令

浅学Warnings

是一种非致命提醒,主要用于警告程序员关于语言或库功能的变化的方法(这里解释了我在控制台看到是用warning而不是用log)
还有一个用法就是警告安装python3.x却试图使用python2.x的功能的开发者,因为python3.x不具有对python2.x的兼容性。 总共分为以下几种(简单介绍下)

UserWarning

警告用户的类型,一般用于开源库或者自建项目对开发者的警告(控制台看到的就是Userwarning)
warn()方法的默认值

DeprecationWarning

顾名思义是已经弃用的功能的警告,可以用于警告使用python2.x功能

PendingDeprecationWarning

未来会被弃用的功能的警告(版本更新之后如果还在使用旧版本的功能)

SyntaxWarning

语法错误警告(漏了括号之类的警告,本人改代码时有漏括号分号之类的情形发生,很痛苦)

UnicodeWarning

编码错误警告

BytesWarning

与bytes和bytearray相关的警告

ResourceWarning

程序没有找到资源或者资源不符合要求的警告

至此,我们理解了为什么会出现UserWarning,以及知道了还有什么类型的warning
但看都看到这了,不妨再看多一点

已经知道warn()方法可以输出类型为UserWarning的警告,但是我又发现在输出警告之后,程序的后面的部分还是可以正常运行
Warnings是一个非致命提醒,那要如何才能让它起到报告异常的作用呢?

了解警告过滤器

警告过滤器是通过警告过滤方法(例如simplefilter()方法)覆盖原有的警告设置,从而达到不同的效果,操作有以下几种

动作执行内容
error将warning转换为exception
ignore关闭warning
always一直打开warning
default在每个位置warning第一次生成时输出
module在每一个Module里warning第一次生成时打印
oncewarning第一次生成时打印(可用于抑制来自不同位置的同一消息的实例)

示例

warnings.simplefilter('error', UserWarning)
#把UserWarning设置为异常,达到遇见UserWarning程序不继续运行的效果

终端使用过滤器

# warnings_filterwarnings_message.py
import warnings
warnings.warn('Show this')
warnings.warn('Do not show this')

输出效果 image.png 终端使用过滤器 image.png

模式过滤

模式过滤是在程序中使用filterwarnings()方法覆盖原值 filters的原值可以进入_warnings.py查看,有Pycharm的可以ctrl+左键点击warn()方法进入

代码实现

这段代码的作用是抑制来自warnings_filterwarnings_message.py的所有UserWarning消息

import warnings

warnings.filterwarnings(
    'ignore',
    '.*',#这里可以写正则表达式
    UserWarning,
    'warnings_filterwarnings_message',
)

import warnings_filterwarnings_message

还有其他消息传递函数,比如logging这些我也不大会,就没记下来
请各位大佬指导