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

发布于 2024-10-31 19:05:48 字数 108 浏览 1 评论 0 原文

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

A third-party library (written in C) that I use in my python code is issuing warnings. I want to be able to use the try except syntax to properly handle these warnings. Is there a way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

给妤﹃绝世温柔 2024-11-07 19:05:48

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

import warnings
warnings.filterwarnings("error")

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

try:
    some_heavy_calculations()
except RuntimeWarning:
    breakpoint()

您还可以通过运行来重置警告的行为:

warnings.resetwarnings()

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

To handle warnings as errors simply use this:

import warnings
warnings.filterwarnings("error")

After this you will be able to catch warnings same as errors, e.g. this will work:

try:
    some_heavy_calculations()
except RuntimeWarning:
    breakpoint()

You can also reset the behaviour of warnings by running:

warnings.resetwarnings()

P.S. Added this answer because the best answer in comments contains misspelling: filterwarnigns instead of filterwarnings.

浮生未歇 2024-11-07 19:05:48

引用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)

To quote from the python handbook (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)
触ぅ动初心 2024-11-07 19:05:48

如果您只是希望脚本在警告时失败,您可以使用 python rel="noreferrer">-W 参数

python -W error foobar.py

If you just want your script to fail on warnings you can invoke python with the -W argument:

python -W error foobar.py
紫罗兰の梦幻 2024-11-07 19:05:48

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

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)

Here's a variation that makes it clearer how to work with only your custom warnings.

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)
飞烟轻若梦 2024-11-07 19:05:48

扩展 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()

Expanding on niekas answer, but using the catch_warnings context manager that resets the warnings behavior to default after context exit:

# 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()
半夏半凉 2024-11-07 19:05:48

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

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

def process_images():
  try:
    some_process()

  except Image.DecompressionBombWarning as e:
    print(e)

Catching all warnings can be problematic. You can catch specific warnings. For example, I needed to catch a Pillow warning:

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

def process_images():
  try:
    some_process()

  except Image.DecompressionBombWarning as e:
    print(e)
零度° 2024-11-07 19:05:48

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

In some cases, you need use ctypes to turn warnings into errors. For example:

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
旧城空念 2024-11-07 19:05:48

为了完整起见,您还可以导出环境变量:

PYTHONWARNINGS=error /usr/bin/run_my_python_utility

Just for completeness, you can also export an env variable:

PYTHONWARNINGS=error /usr/bin/run_my_python_utility
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文