Python:从我的代码中捕获(然后重新抛出)警告

Python: Catching (and then re-throw) warnings from my code

提问人:Xxxo 提问时间:5/23/2023 更新时间:11/21/2023 访问量:48

问:

我想从我的 Python 代码中捕获然后重新抛出警告,类似于 / 子句。我的目的是捕捉警告,然后使用我的记录器重新抛出它。tryexcept

警告是从我使用的任何软件包发出的,我想要一些完全通用的东西,就像 / 子句一样。tryexcept

如何在Python >= v3.8中做到这一点?

python-3.x 警告

评论


答:

1赞 Niko Fohr 11/20/2023 #1

至少有两种方法可以解决这个问题:

  1. 记录警告并重播
  2. 发出警告,使其表现得像异常一样,并中断控制流

选项 1:录制警告并重播

可以使用 warnings.catch_warnings 来记录 Warning 对象。这样,无论出现任何警告,您的所有应用程序代码都将被执行。record=True

import warnings
import logging

logger = logging.getLogger(__name__)


class NotImportantWarning(UserWarning):
    ...


def do_something():
    warnings.warn("doing something", UserWarning)
    warnings.warn("This is not important", NotImportantWarning)


# Executing our main function and recording warnings
with warnings.catch_warnings(record=True) as recorded_warnings:
    do_something()

print("done")

# Handling warnings. You may log it here.
for w in recorded_warnings:
    if isinstance(w.message, NotImportantWarning):
        continue

    # re-issue warning
    warnings.warn_explicit(
        message=w.message,
        category=w.category,
        filename=w.filename,
        lineno=w.lineno,
        source=w.source,
    )
    # or use a logger
    logger.warning(str(w.message))

这将打印出类似的东西

done
<ipython-input-6-cc898056d044>:12: UserWarning: doing something
  warnings.warn("doing something", UserWarning)
doing something

笔记

  • 使用较低级别的warnings.warn_explicit重新发出警告。缺点是可以保留原始文件名和行号信息。warnings.warnwarn_explicit

选项 2:发出警告,使其表现得像异常

如果您真的想在警告时中断控制流,例如出现异常,则可以使用:warnings.filterwarnings("error")

import warnings

warnings.filterwarnings('error')


try:
    do_something()
except UserWarning as w:
    print(w)

注意:代码执行在第一次警告时停止。在该警告之后,内部的任何代码都不会被执行。do_something