获取警告的回溯

emb*_*ert 55 python warnings traceback

在numpy中我们可以做np.seterr(invalid='raise')一个回溯警告而不是引发错误(参见这篇文章).

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

mga*_*gab 74

您可以通过分配获得所需的内容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
Run Code Online (Sandbox Code Playgroud)

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

warnings.simplefilter("always")
Run Code Online (Sandbox Code Playgroud)

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

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

import warnings
warnings.simplefilter("always")
Run Code Online (Sandbox Code Playgroud)

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

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

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

import warnings
warnings.simplefilter("error")
warnings.simplefilter("ignore", DeprecationWarning)
Run Code Online (Sandbox Code Playgroud)

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

  • 这样有用的答案。这些年来,@ embert确实应该将其标记为答案。 (3认同)

Jak*_*yer 21

像你这样运行程序

python -W error myprogram.py
Run Code Online (Sandbox Code Playgroud)

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

  • 这样可行.但是,有没有办法强制python在每个警告上打印回溯.问题是,使用此选项时,程序将在导入期间引发弃用警告时失败. (12认同)
  • 仅供参考,pytest 理解“-W”标志,并且可以使用:“pytest ... -W error”运行(文档:https://docs.pytest.org/en/stable/warnings.html)。根据详细程度,会像任何其他测试失败一样显示回溯 (2认同)

mrt*_*rts 6

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

import warnings
warnings.filterwarnings(
    action='error', message='',
    category=RuntimeWarning
)
Run Code Online (Sandbox Code Playgroud)

就我而言:

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