Wang Tim
Wang Tim

Reputation: 127

How to avoid printing the line that calls an exception or warning in Python?

When I want to throw a warning or exception in Python 3, such as in the following code:

import warnings

def main():
    warnings.warn('This is a warning.')
    raise RuntimeError('This is an exception.')

if __name__=='__main__':
    main()

The terminal tells me in which line the warning or exception was raised:

test_exception.py:4: UserWarning: This is a warning.
  warnings.warn('This is a warning.')
Traceback (most recent call last):
  File "test_exception.py", line 8, in <module>
    main()
  File "test_exception.py", line 5, in main
    raise RuntimeError('This is an exception.')
RuntimeError: This is an exception.

It's nice to know the location, but line 2 and 7 are redundant. Since the contents will be displayed in line 1 and 8. How can I avoid printing the lines that throw an exception or warning? I notice that some packages like Pytorch throw warnings and exceptions elegantly, in exact the way I wish. For example, Pytorch raises exception in the following style:

import torch
import numpy as np
a = torch.from_numpy(np.random.rand(2, 3))
b = torch.from_numpy(np.random.rand(3, 4))
a = a.to('cpu')
b = b.to('cuda:0')
c = torch.mm(a, b)
Traceback (most recent call last):
  File "test_torch_exception.py", line 7, in <module>
    c = torch.mm(a, b)
RuntimeError: Expected object of device type cuda but got device type cpu for argument #1 'self' in call to _th_mm

Upvotes: 1

Views: 2019

Answers (2)

Serge Ballesta
Serge Ballesta

Reputation: 149115

The reference manual is a great source. For the warnings module, it says:

The printing of warning messages is done by calling showwarning(), which may be overridden

And later:

warnings.showwarning(message, category, filename, lineno, file=None, line=None)

... You may replace this function with any callable by assigning to warnings.showwarning.

So just declare your own function special_showwarning with the same parameters, format the output the way you want and simply do: logging.showwarning = special_showwarning.


An equivalent way is possible for exception by overriding sys.excepthook:

sys.excepthook(type, value, traceback)

This function prints out a given traceback and exception to sys.stderr.

When an exception is raised and uncaught, the interpreter calls sys.excepthook with three arguments... The handling of such top-level exceptions can be customized by assigning another three-argument function to sys.excepthook.

Unfortunately, this may not work when executing python code in an IDE, for example IDLE uses a custom loop and does not call sys.excepthook. In that case, you could simply wrap your current main in a try block and catch anything. It is then easy to display what you want:

def main():
    # your code ...

if __name__ == '__main__':
    try:
        main()
    except:
        type, value, traceback = sys.exc_info()
        # add your error formatting here

Upvotes: 3

Peter Parker
Peter Parker

Reputation: 29725

If you change your source code slightly to a real life situation it becomes maybe clearer why the behavior is like this:

import warnings
warn = 'This is a warning'
exception = 'This is an exception'

def main():
    warnings.warn(warn)
    raise RuntimeError(exception)

if __name__=='__main__':
    main()

Now the output is:

test_exception.py:6: UserWarning: This is a warning
  warnings.warn(warn)
Traceback (most recent call last):
  File "C:\Users\11ldornbusch\Desktop\2del.py", line 10, in <module>
    main()
  File "C:\Users\11ldornbusch\Desktop\2del.py", line 7, in main
    raise RuntimeError(exception)
RuntimeError: This is an exception

So if you use variables your output shows in one line the content of the variable, and in the other the name. This can give you more context on what the problem is, for example a "Nothing" as output will gives you also the name of the variable which is nothing.

You can also use logging or Hook the output in python to modify the output of the warning: From the documentation available here: https://docs.python.org/3/library/warnings.html

The printing of warning messages is done by calling showwarning(), which may be overridden; the default implementation of this function formats the message by calling formatwarning(), which is also available for use by custom implementations.

Upvotes: 1

Related Questions