warnings
warnings - 警告控制
2.1版本中的新功能。
源代码:
Lib / warnings.py
警告消息通常是在有用的情况下发出的,以提醒用户程序中的某些条件,其中该条件(通常)不能保证引发异常并终止程序。例如,当程序使用过时的模块时,可能会发出警告。
Python程序员通过调用warn()
本模块中定义的函数来发出警告。(C程序员使用PyErr_WarnEx(
有关详细信息,请参阅异常处理)。
警告信息通常会写入sys.stderr
,但其配置可以灵活地进行更改,从忽略所有警告到将其变为例外。警告的处置可能因警告类别(见下文),警告消息的文本以及发出警告的来源位置而异。通常会抑制针对相同源位置的特定警告的重复。
警告控制分为两个阶段:首先,每发出一次警告,就确定是否应该发布消息; 接下来,如果要发布消息,则使用用户可设置的钩子将其格式化并打印。
警告过滤器控制是否发出警告消息,这是一系列匹配规则和操作。 可以通过调用filterwarnings()将规则添加到过滤器,并通过调用resetwarnings()将其重置为默认状态。
警告消息的打印通过调用完成showwarning()
,可能会被覆盖; 该函数的默认实现通过调用来格式化消息formatwarning()
,这也可供自定义实现使用。
扩展内容
logging.captureWarnings()
允许您使用标准日志记录基础结构处理所有警告。
1.警告类别
有许多代表警告类别的内置异常。此分类对于能够过滤出多组警告很有用。目前定义了以下警告类别类别:
类 | 描述 |
---|---|
Warning | 这是所有警告类别类的基类。它是Exception的一个子类。 |
UserWarning | warn()的默认类别。 |
DeprecationWarning | 有关不推荐使用的功能的警告的基本类别(默认情况下被忽略)。 |
SyntaxWarning | 基本类别,用于警告关于可疑语法特征的警告。 |
RuntimeWarning | 有关可疑运行时功能的警告的基本类别。 |
FutureWarning | 关于构造的警告的基本类别将在未来语义上发生变化。 |
PendingDeprecationWarning | 基本类别,用于警告将来不推荐使用的功能(默认情况下会被忽略)。 |
ImportWarning | 在导入模块的过程中触发警告的基本类别(默认情况下会被忽略)。 |
UnicodeWarning | 与Unicode相关的警告的基本类别。 |
虽然这些技术上是内置的例外,但它们在这里被记录,因为它们在概念上属于警告机制。
用户代码可以通过继承其中一个标准警告类别来定义其他警告类别。警告类别必须始终是Warning
该类的一个子类。
在版本2.7中更改:DeprecationWarning
默认情况下被忽略。
2.警告过滤器
警告过滤器控制警告是否被忽略,显示或转化为错误(引发异常)。
从概念上讲,警告过滤器维护过滤器规格的有序列表; 任何特定的警告依次与列表中的每个过滤规范进行匹配,直到找到匹配; 比赛决定比赛的处置。每个条目都是表单(action
,message
,category
,module
,lineno
)的元组,其中:
action
是以下字符串之一:Value Disposition"error"
将匹配警告转化为例外"ignore"
从不打印匹配警告"always"
始终打印匹配警告"default"
为发出警告的每个位置打印匹配警告的第一次匹配"module"
打印每个模块的匹配警告"once"
只打印第一次出现的匹配警告,无论位置如何
message
是一个包含正则表达式的字符串,警告消息的开头必须匹配。该表达式被编译为始终不区分大小写。
category
是一个类(其子类Warning
),为了匹配,警告类别必须是子类。
module
是一个包含模块名称必须匹配的正则表达式的字符串。该表达式被编译为区分大小写。
- lineno是发生警告的行号必须匹配的整数,或0以匹配所有行号。
由于Warning类是从内置的Exception类派生的,为了将警告转化为错误,我们只需提高类别(消息)。
警告过滤器由传递给Python解释器命令行的-W选项初始化。 解释器将所有-W选项的参数保存在sys.warnoptions中,而无需解释; 警告模块在首次导入时解析这些信息(在将消息输出到sys.stderr后,忽略无效选项)。
2.1。默认警告过滤器
默认情况下,Python会安装多个警告过滤器,这些警告过滤器可以通过传递给-W的命令行选项和调用filterwarnings()来覆盖。
DeprecationWarning
和PendingDeprecationWarning
,且ImportWarning
被忽略。
BytesWarning
被忽略,除非该-b
选项给出一次或两次; 在这种情况下,这个警告要么被打印(-b
),要么变成异常(-bb
)。
3.暂时禁止警告
如果您使用的代码会引发警告(例如不推荐使用的函数),但不希望看到警告,则可以使用catch_warnings上下文管理器来抑制警告:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
在上下文管理器中,所有的警告都将被忽略。这使您可以使用已知不推荐的代码,而不必查看警告,同时不抑制其他可能不知道其使用弃用代码的代码的警告。注意:这只能在单线程应用程序中保证。如果两个或更多线程同时使用catch_warnings
上下文管理器,则行为是未定义的。
4.测试警告
要测试代码引发的警告,请使用catch_warnings
上下文管理器。有了它,您可以暂时改变警告筛选器以方便您的测试。例如,执行以下操作捕获所有引发的警告以检查:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
也可以通过使用错误而不是始终使所有警告成为例外。 需要注意的一件事是,如果由于一次/默认规则已经引发了警告,那么无论设置了哪些过滤器,除非与警告相关的警告注册表已被清除,否则不会再次看到该警告。
一旦上下文管理器退出,警告过滤器将恢复到输入上下文时的状态。这可以防止测试在测试之间以意外的方式更改警告过滤器,并导致不确定的测试结果。showwarning()
模块中的功能也恢复到其原始值。注意:这只能在单线程应用程序中保证。如果两个或更多线程同时使用catch_warnings
上下文管理器,则行为是未定义的。
在测试引发同类警告的多个操作时,重要的是要以确认每个操作引发新警告的方式对它们进行测试(例如,将警告设置为例外并检查操作是否引发异常,检查长度警告列表在每次操作后继续增加,或者在每次新操作之前从警告列表中删除以前的条目)。
5.更新Python新版本的代码
只有开发者感兴趣的警告在默认情况下被忽略。 因此,您应该确保通过可见的通常被忽略的警告来测试您的代码。 您可以通过将-Wd传递给解释器(这是-W默认的简写)从命令行执行此操作。 这将启用默认处理所有警告,包括默认情况下忽略的警告。 要改变对遇到的警告采取的行动,你只需要改变传递给-W的参数,例如 -W错误。 有关可能的更多细节,请参阅-W标志。
要以编程方式执行相同的操作-Wd
,请使用:
warnings.simplefilter('default')
确保尽快执行此代码。这可以防止注册已经引发的警告,从而意外地影响将来的警告如何被处理。
默认情况下会忽略某些警告,以防止用户看到仅由开发人员感兴趣的警告。 由于您不一定能够控制用户使用哪些解释器来运行其代码,因此可能会在您的发布周期之间发布新版本的Python。 新的解释器版本可能会在您的代码中触发新的警告,而这些警告在旧版本的解释器中不存在,例如 DeprecationWarning您正在使用的模块。 尽管作为开发人员希望得到您的代码使用已弃用模块的通知,但对用户而言,此信息本质上是噪声,并且不会给他们带来任何好处。
6.可用功能
warnings.warn(message[, category[, stacklevel]])
发出警告,或者忽略它或引发异常。 类别参数(如果给出)必须是警告类别类(参见上文); 它默认为UserWarning。 或者,消息可以是一个Warning实例,在这种情况下,类别将被忽略,并且将使用消息.__ class__。 在这种情况下,消息文本将是str(消息)。 如果发出的特定警告被上述警告过滤器更改为错误,则此功能会引发异常。 用Python编写的包装函数可以使用stacklevel参数,如下所示:
def deprecation(message):
warnings.warn(message, DeprecationWarning, stacklevel=2)
这使得警告指deprecation()
的是调用者,而不是deprecation()
它本身的源头(因为后者会打败警告信息的目的)。
warnings.warn_explicit(message, category, filename, lineno[, module[, registry[, module_globals]]])
这是warn()函数的低级接口,明确传递消息,类别,文件名和行号,以及可选的模块名称和注册表(应该是模块的__warningregistry__字典)。 模块名称默认为带.py的剥离文件名; 如果没有通过注册表,警告从不被抑制。 消息必须是字符串,并且类别的警告或消息的子类可以是警告实例,在这种情况下,类别将被忽略。
module_globals
(如果提供)应该是发出警告的代码所使用的全局名称空间。(此参数用于支持显示zip文件或其他非文件系统导入源中找到的模块的源代码)。
在版本2.5中更改:添加了module_globals
参数。
warnings.warnpy3k(message[, category[, stacklevel]])
发出与Python 3.x弃用相关的警告。 警告仅在使用-3选项启动Python时显示。 和warn()一样,消息必须是一个字符串,而类别是Warning的一个子类。 warnpy3k()使用DeprecationWarning作为默认警告类。
2.6版本中的新功能。
warnings.showwarning(message, category, filename, lineno[, file[, line]])
给文件写一个警告。 缺省实现调用formatwarning(消息,类别,文件名,行号,行)并将结果字符串写入文件,缺省值为sys.stderr。 您可以通过分配给warnings.showwarning将其替换为替代实现。 行是要包含在警告消息中的一行源代码; 如果未提供行,showwarning()将尝试读取由filename和lineno指定的行。
在版本2.7中更改:需要支持行
参数。
warnings.formatwarning(message, category, filename, lineno[, line])
以标准方式格式化警告。 这将返回一个可能包含嵌入换行符并以换行符结尾的字符串。 行是要包含在警告消息中的一行源代码; 如果未提供行,formatwarning()将尝试读取由filename和lineno指定的行。
在版本2.6中更改:添加了行
参数。
warnings.filterwarnings(action[, message[, category[, module[, lineno[, append]]]]])
将条目插入警告筛选器规范列表中。该条目默认插入在前面; 如果append
为true,则在最后插入。这将检查参数的类型,编译消息
和模块
正则表达式,并将它们作为元组插入警告过滤器列表中。如果两个条目都匹配一个特定的警告,那么靠近列表前面的条目会覆盖列表中稍后的条目。省略参数默认为匹配所有内容的值。
warnings.simplefilter(action[, category[, lineno[, append]]])
将简单条目插入警告筛选器规范列表中。 函数参数的含义与filterwarnings()相同,但不需要正则表达式,因为只要类别和行号匹配,插入的过滤器就会始终匹配任何模块中的任何消息。
warnings.resetwarnings()
重置警告过滤器。 这将放弃之前调用filterwarnings()的所有调用的效果,包括-W命令行选项的调用和对simplefilter()的调用。
7.可用的上下文管理器
class warnings.catch_warnings([*, record=False, module=None])
复制的上下文管理器,并且在退出时恢复警告过滤器和showwarning()函数。 如果record参数为False(缺省值),则上下文管理器在条目上返回None。 如果记录为True,则会返回一个列表,如自定义的showwarning()函数(它也抑制输出到sys.stdout)所看到的那样逐渐填充对象。 列表中的每个对象都具有与showwarning()的参数具有相同名称的属性。
模块参数需要一个将被使用的模块,而不是导入过滤器将受到保护的警告时返回的模块。 该参数主要用于测试警告模块本身。
注意
catch_warnings管理器的工作方式是替换并稍后恢复模块的showwarning()函数和过滤器规范的内部列表。 这意味着上下文管理器正在修改全局状态,因此不是线程安全的。
注意
在Python 3中,catch_warnings构造函数的参数是关键字参数。
2.6版本中的新功能。