关于python:获取警告的回溯

Get Traceback of warnings

在numpy中,我们可以执行np.seterr(invalid='raise')来获取警告引发错误的回溯(请参阅此文章)。

  • 是否有跟踪警告的一般方法?
  • 当发出警告时,我可以让python进行追溯吗?


您可以通过分配到warnings.showwarning来获得所需内容。警告模块文档本身建议您这样做,因此并不是因为您受到源的黑暗面的诱惑。 :)

You may replace this function with an alternative implementation by assigning to warnings.showwarning.

您可以定义一个新函数来执行warning.showwarning正常执行的操作,此外它还会打印堆栈。然后你把它放在原来的地方:

1
2
3
4
5
6
7
8
9
10
11
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

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

1
warnings.simplefilter("always")

您可以通过warning模块的过滤器获得一个numpy.seterr提供的类似控件

如果您想要的是python每次触发时都会报告每个警告,而不仅仅是第一次,您可以包含以下内容:

1
2
import warnings
warnings.simplefilter("always")

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

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

例如,您可以设置所有警告以引发异常,但应完全忽略的DeprecationWarnings除外:

1
2
3
import warnings
warnings.simplefilter("error")
warnings.simplefilter("ignore", DeprecationWarning)

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


像你这样运行程序

1
python -W error myprogram.py

这使得所有警告都致命,请参阅此处以获取更多信息