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

问题描述 投票:0回答:1

我想捕获并重新抛出 Python 代码中的警告,类似于

try
/
except
子句。我的目的是捕获警告,然后使用我的记录器重新抛出它。

警告是从我使用的任何软件包发出的,我想要完全通用的东西,就像

try
/
except
子句一样。

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

python python-3.x warnings
1个回答
1
投票

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

  1. 记录警告并重播
  2. 使警告表现得像异常并打破控制流

选项 1:记录警告并重播

您可以使用 warnings.catch_warnings

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 reversed(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

注释

  • 使用
    reversed(recorded_warnings)
    将警告按其出现的顺序排列。
  • 使用较低级别的warnings.warn_explicit重新发出警告。
    warnings.warn
    的好处是使用
    warn_explicit
    可以保留原始文件名和行号信息。

选项 2:使警告表现得像异常一样

如果你真的想在警告时立即中断控制流,就像异常一样,可以使用

warnings.filterwarnings("error")
:

import warnings

warnings.filterwarnings('error')


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

注意:代码执行在第一次警告时停止。在该警告之后,

do_something
内的任何代码都不会被执行。

© www.soinside.com 2019 - 2024. All rights reserved.