我想捕获并重新抛出 Python 代码中的警告,类似于
try
/except
子句。我的目的是捕获警告,然后使用我的记录器重新抛出它。
警告是从我使用的任何软件包发出的,我想要完全通用的东西,就像
try
/except
子句一样。
如何在 Python >= v3.8 中做到这一点?
至少有两种方法可以解决这个问题:
您可以使用 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
的好处是使用 warn_explicit
可以保留原始文件名和行号信息。如果你真的想在警告时立即中断控制流,就像异常一样,可以使用
warnings.filterwarnings("error")
:
import warnings
warnings.filterwarnings('error')
try:
do_something()
except UserWarning as w:
print(w)
注意:代码执行在第一次警告时停止。在该警告之后,
do_something
内的任何代码都不会被执行。