获取警告回溯

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

在 numpy 中,我们可以执行

np.seterr(invalid='raise')
来获取引发错误的警告的回溯(请参阅这篇文章)。

  • 有追踪警告的通用方法吗?
  • 当出现警告时,我可以让 python 进行回溯吗?
python warnings traceback
5个回答
143
投票

你可以通过分配给

warnings.showwarning
来得到你想要的。 警告模块文档本身建议您这样做,所以这并不是说您受到了源代码的阴暗面的诱惑。 :)

您可以通过分配给

warnings.showwarning
来用替代实现替换此函数。

您可以定义一个新函数来执行

warning.showwarning
通常所做的事情,此外它还会打印堆栈。然后你将它代替原来的:

import traceback
import warnings
import sys

def warn_with_traceback(message, category, filename, lineno, file=None, line=None):

    log = file if hasattr(file,'write') else sys.stderr
    traceback.print_stack(file=log)
    log.write(warnings.formatwarning(message, category, filename, lineno, line))

warnings.showwarning = warn_with_traceback

此后,每个警告都会打印堆栈跟踪以及警告消息。但要考虑到,如果警告因为不是第一个而被忽略,则不会发生任何事情,因此您仍然需要执行:

warnings.simplefilter("always")

您可以通过

numpy.seterr
模块的过滤器获得与
warning
提供的类似控制

如果你想要的是 python 在每次触发时报告每个警告,而不仅仅是第一次,你可以包括类似的内容:

import warnings
warnings.simplefilter("always")

您可以通过传递不同的字符串作为参数来获得其他行为。使用相同的函数,您还可以指定不同的警告行为,具体取决于引发警告的模块、它们提供的消息、警告类、导致警告的代码行等等...

您可以在模块文档中查看列表

作为示例,您可以设置所有警告以引发异常,但应完全忽略的

DeprecationWarnings
除外:

import warnings
warnings.simplefilter("error")
warnings.simplefilter("ignore", DeprecationWarning)

通过这种方式,您可以获得作为错误引发的每个警告的完整回溯(只有第一个警告,因为执行将停止......但您可以逐个解决它们,并创建一个过滤器来忽略您不想处理的警告)再次听说...


49
投票

像这样运行你的程序

python -W error myprogram.py

这使得所有警告都是致命的,请参阅此处了解更多信息


6
投票

您可以使用

warnings.filterwarnings()
将选定的警告转换为异常并获取回溯。最小工作示例如下:

import warnings
warnings.filterwarnings(
    action='error', message='',
    category=RuntimeWarning
)

就我而言:

import warnings
warnings.filterwarnings(
    'error', 'DateTimeField .* received a naive datetime',
    RuntimeWarning, 'django.db.models.fields'
)

2
投票

对于 Python3,请参阅

warnings
模块文档中的 stacklevel 参数。当第 3 方警告隐藏在调用堆栈中时,这尤其有用:将 warnings.warn 调用参数设置为
stacklevel=2
,查看回溯,在必要时进行更改,将堆栈级别恢复/删除到原始状态。

例如:

warnings.warn("It's dangerous to go alone! Take this.", stacklevel=2)

1
投票

记录警告的选项,对程序流程的干扰最小。
获取回溯而不引发错误:

import warnings
import traceback

warnings.filterwarnings("error")  # Treat warnings as errors
try:
    your_code()
except Warning:
    print(traceback.format_exc())  # print traceback
warnings.resetwarnings()  # Back to default behavior

如果您想以任何一种方式执行相同(或相似)的代码,您可以在

except
块中执行它,这次忽略警告,因为您已经得到了它的回溯:

import warnings
import traceback

warnings.filterwarnings("error")  # Treat warnings as errors
try:
    your_code()
except Warning:
    print(traceback.format_exc())  # print traceback
    warnings.filterwarnings("ignore")  # ignore warnings
    your_code()  # Execute either way (same code or alternative code)
warnings.resetwarnings()  # Back to default behavior
© www.soinside.com 2019 - 2024. All rights reserved.