My minimum example is
#!/usr/bin/python3
import warnings
warnings.warn(\'Run Forest run!\', stacklevel=2)
warnings.warn(\'Run Forest run!\')
The reason you are getting the "redundant" line is because if you don't provide the stacklevel
parameter the default stacklevel
is 1, which is basically telling the user the exact line of code that the warning originated from, which is your warning function call warnings.warn('Run Forest Run!')
.
If you're not happy with the way it functions, you can use the warnings.warn_explicit()
function to customise it.
https://docs.python.org/3.1/library/warnings.html#available-functions
Turns out it is possible to let warnings.warn()
collect all the info and just costumize the way the info is printed:
#!/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!')
Output:
sys:1: UserWarning: Run Forest run!
./file.py:15: UserWarning: Run Forest run!
Source: Python module of the week
In case you're trying to catch exception/error, and want to see both your custom warning message and traceback, you might prefer to use traceback.print_exc() :
import traceback
import warnings
def _formatwarning(msg, *a):
try:
traceback.print_exc()
except:
pass
return str(msg)
warnings.formatwarning = _formatwarning
which will make warn("your message") print traceback without mention the call to warn() itself.
UPDATE: on Python 3.6 you need to change function signature to:
def _formatwarning(message, category, filename, lineno, line='')