在线文档教程

warnings

warnings - 警告控制

2.1版本中的新功能。

源代码: Lib / warnings.py

警告消息通常是在有用的情况下发出的,以提醒用户程序中的某些条件,其中该条件(通常)不能保证引发异常并终止程序。例如,当程序使用过时的模块时,可能会发出警告。

Python程序员通过调用warn()本模块中定义的函数来发出警告。(C程序员使用PyErr_WarnEx( 有关详细信息,请参阅异常处理)。

警告信息通常会写入sys.stderr,但其配置可以灵活地进行更改,从忽略所有警告到将其变为例外。警告的处置可能因警告类别(见下文),警告消息的文本以及发出警告的来源位置而异。通常会抑制针对相同源位置的特定警告的重复。

警告控制分为两个阶段:首先,每发出一次警告,就确定是否应该发布消息; 接下来,如果要发布消息,则使用用户可设置的钩子将其格式化并打印。

警告过滤器控制是否发出警告消息,这是一系列匹配规则和操作。 可以通过调用filterwarnings()将规则添加到过滤器,并通过调用resetwarnings()将其重置为默认状态。

警告消息的打印通过调用完成showwarning(),可能会被覆盖; 该函数的默认实现通过调用来格式化消息formatwarning(),这也可供自定义实现使用。

扩展内容

logging.captureWarnings() 允许您使用标准日志记录基础结构处理所有警告。

1.警告类别

有许多代表警告类别的内置异常。此分类对于能够过滤出多组警告很有用。目前定义了以下警告类别类别:

描述
Warning 这是所有警告类别类的基类。它是Exception的一个子类。
UserWarningwarn()的默认类别。
DeprecationWarning有关不推荐使用的功能的警告的基本类别(默认情况下被忽略)。
SyntaxWarning基本类别,用于警告关于可疑语法特征的警告。
RuntimeWarning有关可疑运行时功能的警告的基本类别。
FutureWarning关于构造的警告的基本类别将在未来语义上发生变化。
PendingDeprecationWarning基本类别,用于警告将来不推荐使用的功能(默认情况下会被忽略)。
ImportWarning在导入模块的过程中触发警告的基本类别(默认情况下会被忽略)。
UnicodeWarning与Unicode相关的警告的基本类别。

虽然这些技术上是内置的例外,但它们在这里被记录,因为它们在概念上属于警告机制。

用户代码可以通过继承其中一个标准警告类别来定义其他警告类别。警告类别必须始终是Warning该类的一个子类。

在版本2.7中更改:DeprecationWarning默认情况下被忽略。

2.警告过滤器

警告过滤器控制警告是否被忽略,显示或转化为错误(引发异常)。

从概念上讲,警告过滤器维护过滤器规格的有序列表; 任何特定的警告依次与列表中的每个过滤规范进行匹配,直到找到匹配; 比赛决定比赛的处置。每个条目都是表单(actionmessagecategorymodulelineno)的元组,其中:

  • 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()来覆盖。

  • DeprecationWarningPendingDeprecationWarning,且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版本中的新功能。