在Python中,如何将警告当作异常捕获?

在Python中,如何将警告当作异常捕获?,python,exception,exception-handling,warnings,Python,Exception,Exception Handling,Warnings,我在python代码中使用的第三方库(用C编写)发出警告。我希望能够使用try语法来正确处理这些警告。有办法做到这一点吗?引用python手册(): 这里有一个变体,可以更清楚地说明如何仅使用自定义警告 import warnings with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always")

我在python代码中使用的第三方库(用C编写)发出警告。我希望能够使用
try
语法来正确处理这些警告。有办法做到这一点吗?

引用python手册():


这里有一个变体,可以更清楚地说明如何仅使用自定义警告

import warnings
with warnings.catch_warnings(record=True) as w:
    # Cause all warnings to always be triggered.
    warnings.simplefilter("always")

    # Call some code that triggers a custom warning.
    functionThatRaisesWarning()

    # ignore any non-custom warnings that may be in the list
    w = filter(lambda i: issubclass(i.category, UserWarning), w)

    if len(w):
        # do something with the first warning
        email_admins(w[0].message)

要将警告作为错误处理,只需使用以下命令:

import warnings
warnings.filterwarnings("error")
在此之后,您将能够捕获与错误相同的警告,例如,这将起作用:

try:
    some_heavy_calculations()
except RuntimeWarning:
    import ipdb; ipdb.set_trace()

另外,添加此答案是因为注释中的最佳答案包含拼写错误:
filterwarnings
而不是
filterwarnings

如果您只想让脚本在警告时失败,可以使用以下命令调用
python


在某些情况下,您需要使用ctypes将警告转换为错误。例如:

str(b'test')  # no error
import warnings
warnings.simplefilter('error', BytesWarning)
str(b'test')  # still no error
import ctypes
ctypes.c_int.in_dll(ctypes.pythonapi, 'Py_BytesWarningFlag').value = 2
str(b'test')  # this raises an error
展开,但使用上下文管理器在上下文退出后将警告行为重置为默认值:

import warnings

with warnings.catch_warnings():
     warnings.simplefilter("error")
     # Code in this block will raise exception for a warning
# Code in this block will have default warning behaviour

那些警告仅仅是写在stderr上的短信吗?Fenikso:我不确定,看起来像是真正的警告你怎么认识“真正的警告”?我认为在C语言中,你在编译时会得到真正的警告。
警告。filterwarnings
正是你想要的,我不明白你的问题是什么?@Fenikso,@Rosh Oxymoron你是对的。我的错误<代码>警告。过滤器警告('error')
执行此任务。我找不到提出此解决方案的原始答案,它告诉您如何使用
try
语法,除了
语法。与niekas的答案相比,这有一个优势,即如果
fnx
返回某个内容,您将保留该结果(并且仍然可以管理警告)。这并没有回答OP的问题,这是关于处理wanring,而不是测试它们。但是,下面niekas的回答确实说明了如何处理警告。请注意,如果函数只是间歇性地返回警告,则上述函数将不起作用,因为如果
fxn()
不返回警告,则
w
将是一个空列表。如果
w
是一个空列表(即
[]
),则运行该代码将出现以下错误:
索引器:列表索引超出范围
。如果您只是想格式化或检查捕获的警告的属性,那么最好使用for循环:
for x in w:print(f'{x.category.\uu name.\uu}:{str(x.message)}')
如果希望在不中断程序执行的情况下处理警告,这种方法非常有用,前两行就是你所需要的。这太完美了。我只是希望我的脚本在发出警告后立即停止执行,这样我就可以打印相关的调试信息并修复问题。至少在python 3中,您不需要调用
filterwarnings
来捕获
警告。它只是起作用。被接受的答案并不能回答OP的问题。答案是肯定的。这就是我在搜索中发现此问题时所寻找的答案。如果在较大的脚本或软件包中使用此选项,则将所有警告转换为错误很容易出现问题。也会使调试变得非常困难。这个答案很有建设性,只是为了说明如何只在某些警告类型中出错。对于几乎任何大型软件项目,如果执行
warnings.simplefilter('error')
操作,您将不会获得日志中看到的警告的回溯,而是从以前过滤的警告中获取回溯。如果有一些CLI调用,使用
simplefilter
也是获得答案的最快方法。
str(b'test')  # no error
import warnings
warnings.simplefilter('error', BytesWarning)
str(b'test')  # still no error
import ctypes
ctypes.c_int.in_dll(ctypes.pythonapi, 'Py_BytesWarningFlag').value = 2
str(b'test')  # this raises an error
import warnings

with warnings.catch_warnings():
     warnings.simplefilter("error")
     # Code in this block will raise exception for a warning
# Code in this block will have default warning behaviour