在Python中,如何捕获警告,就好像它们是例外?

Bor*_*lik 87 python warnings exception-handling exception

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

nie*_*kas 102

要将警告视为错误,只需使用:

import warnings
warnings.filterwarnings("error")
Run Code Online (Sandbox Code Playgroud)

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

try:
    some_heavy_calculations()
except RuntimeWarning:
    import ipdb; ipdb.set_trace()
Run Code Online (Sandbox Code Playgroud)

PS添加了这个答案,因为评论中的最佳答案包含拼写错误:filterwarnigns而不是filterwarnings.

  • 如果您只想查看堆栈跟踪,前两行就是您所需要的. (6认同)
  • 太棒了.我只是希望我的脚本在发出警告后立即停止执行,以便我可以打印相关的调试信息并解决问题. (3认同)
  • 你不需要`filterwarnings` 调用来捕捉`Warnings`,至少在python 3 中是这样。它只是有效。 (2认同)
  • 完成后使用 warnings.resetwarnings() 进行重置 (2认同)

Bob*_*ers 39

引用python手册(27.6.4.测试警告):

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)
Run Code Online (Sandbox Code Playgroud)

  • [这里](http://stackoverflow.com/a/15934081/461597)是一个答案,它告诉你如何使用`try`` except`语法. (4认同)
  • 与 niekas 的答案相比,这有一个优点,即如果“fnx”返回某些内容,您将保留该结果(并且仍然可以管理警告)。 (3认同)

mcq*_*rty 14

这是一个变体,它使您更清楚如何使用自定义警告.

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)
Run Code Online (Sandbox Code Playgroud)


azm*_*euk 14

如果您只是希望脚本在警告时失败,您可以使用:

python -W error foobar.py
Run Code Online (Sandbox Code Playgroud)

  • 捕获特定的警告类型,例如:`python -W error::RuntimeWarning foobar.py` (10认同)

Cha*_*esB 14

扩展niekas 答案,但使用catch_warnings上下文管理器在上下文退出后将警告行为重置为默认值:

# works in python 3.8: https://docs.python.org/3.8/library/warnings.html
import warnings
with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fn_triggering_warnings()

# works in python 3.11: https://docs.python.org/3.11/library/warnings.html
import warnings
with warnings.catch_warnings(action="ignore"):
    fn_triggering_warnings()
Run Code Online (Sandbox Code Playgroud)


小智 9

捕获所有警告可能会出现问题。您可以捕获特定的警告。例如,我需要捕获枕头警告:

import warnings
warnings.filterwarnings("error", category=Image.DecompressionBombWarning)

def process_images():
  try:
    some_process()

  except Image.DecompressionBombWarning as e:
    print(e)
Run Code Online (Sandbox Code Playgroud)


Col*_*son 5

在某些情况下,您需要使用 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
Run Code Online (Sandbox Code Playgroud)