让Python的`warnings.warn()`不提及自身

19 投票
3 回答
4960 浏览
提问于 2025-04-28 04:17

我的最简单例子是

#!/usr/bin/python3

import warnings

warnings.warn('Run Forest run!', stacklevel=2)
warnings.warn('Run Forest run!')

它会输出

sys:1: UserWarning: Run Forest run!
./file.py:6: UserWarning: Run Forest run!
  warnings.warn('Run Forest run!')

第一行给我的信息太少了。第二行很完美,告诉我源文件和行号……但我想去掉多余的第三行。这样做可以吗?

暂无标签

3 个回答

2

如果你想捕捉异常或错误,并且希望同时看到你自己定义的警告信息和错误追踪信息,你可以使用 traceback.print_exc():

import traceback
import warnings

def _formatwarning(msg, *a):
   try:
       traceback.print_exc()
   except:
       pass
   return str(msg)

warnings.formatwarning = _formatwarning

这样的话,warn("你的信息") 就会打印出错误追踪信息,而不会提到 warn() 这个函数本身的调用。

更新:在 Python 3.6 中,你需要把函数的定义改成:

def _formatwarning(message, category, filename, lineno, line='')
6

你看到“多余”的提示是因为如果你不提供 stacklevel 参数,默认的 stacklevel 是 1。这意味着它会告诉用户警告是从哪一行代码发出的,也就是你调用的警告函数 warnings.warn('Run Forest Run!')

如果你觉得这样不太好,可以使用 warnings.warn_explicit() 函数来进行自定义。

https://docs.python.org/3.1/library/warnings.html#available-functions

17

原来可以让 warnings.warn() 收集所有信息,然后只需要自定义信息的打印方式:

#!/usr/bin/python3

import warnings

def warning_on_one_line(message, category, filename, lineno, file=None, line=None):
    return '%s:%s: %s: %s\n' % (filename, lineno, category.__name__, message)

warnings.formatwarning = warning_on_one_line

warnings.warn('Run Forest run!', stacklevel=2)
warnings.warn('Run Forest run!')

输出结果:

sys:1: UserWarning: Run Forest run!
./file.py:15: UserWarning: Run Forest run!

来源: 本周的Python模块

撰写回答