在Python中,如何将警告视为异常?


103

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


2
这些警告只是写在stderr上的短信吗?
Fenikso 2011年

1
Fenikso:我不确定,这似乎是真正的警告
Boris Gorelik

1
您如何识别“真实警告”?我认为在C语言中,您在编译期间会收到真正的警告。
Fenikso 2011年

warnings.filterwarnings到底是您想要的,我不知道您的问题是什么?
Rosh Oxymoron

4
@ Fenikso,@ Rosh Oxymoron,你是对的。我的错。warnings.filterwarnigns('error')做这份工作。我找不到提出该解决方案的原始答案
Boris Gorelik

Answers:


51

引用python手册(27.6.4。Testing 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)

6
是一个答案,告诉您如何使用try except语法。
Unapiedra 2014年

与niekas的答案相比,这样做的优势在于,如果fnx返回某些内容,则可以保留该结果(并且仍然可以管理警告)。
Pietro Battiston,

这不能回答OP的问题,该问题是关于处理错觉而不是对其进行测试。但是,下面的niekas回答确实显示了如何处理警告。
Biggsy

请注意,如果您的函数仅间歇性地返回警告,则上述函数将不起作用,因为在fxn()不返回警告的情况下,w它将是一个空列表。如果w是空列表(即[]),则运行代码将给您以下错误:IndexError: list index out of range。如果您只是想格式化或检查捕获的警告的属性,那么最好使用for循环:for x in w: print(f'{x.category.__name__}: {str(x.message)}')
Steven M. Mortimer

130

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

import warnings
warnings.filterwarnings("error")

之后,您将能够捕获与错误相同的警告,例如,它将起作用:

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

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


8
如果只想查看堆栈跟踪,则只需要前两行。
z0r

5
太棒了。我只是希望脚本在发出警告后立即停止执行,因此我可以打印相关的调试信息并解决问题。
Praveen

1
至少在python 3中,您不需要filterwarnings调用即可catch Warnings,它只是有效。
naught101 '19

1
接受的答案不会回答OP的问题。这个答案可以。这是我的搜索找到此问题时正在寻找的答案。
Biggsy


15

这是一个变体,可让您更清楚地了解如何仅使用自定义警告。

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)

4

在某些情况下,您需要使用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

该答案仅用于说明如何仅在某些警告类型中出现错误才具有建设性。对于几乎所有大型软件项目,如果您这样做warnings.simplefilter('error'),都不会获得在日志中看到的警告的回溯,而是从先前过滤的警告中获得回溯。simplefilter如果您有一些CLI调用,则使用也是获得答案的最快方法。
AlanSE
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.