18

Is there a way to get a "prettier" exception rather than one prefaced with __main__MyExceptionTitle?

Example:

>>> class BadThings(Exception):
...     def __init__(self, msg):
...         self.msg = msg
...         return
... 
>>> class BadThings(Exception):
...     def __init__(self, msg):
...         self.msg = msg
...         return
...     def __str__(self):
...         return self.msg
... 
>>> raise BadThings("This is really, really bad")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.BadThings: This is really, really bad

I would like it to just say:

BadThings: This is really, really bad

Just as if one types:

>>> raise Exception("This, too, is really, really bad")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception: This, too, is really, really bad

I would like the __main__. gone!

Thanks, Narnie

johnsyweb
  • 136,902
  • 23
  • 188
  • 247
narnie
  • 1,742
  • 1
  • 18
  • 34

4 Answers4

19
class MyException(Exception):
    __module__ = Exception.__module__

This way looks/works better than sys.excepthook


Source Code Reference

Python2

See PyErr_Display

There're two ways to bypass the module name part:

class A(Exception):
    __module__ = None

class B(Exception):
    __module__ = 'exceptions'

But if you need to play with threading.Thread, the first one will introduce a TypeError.

Python 3

See PyErr_WriteUnraisable

class C(Exception):
    __module__ = 'builtins'
youfu
  • 1,547
  • 3
  • 15
  • 21
  • This is great! However, I ran into a problem when I subclassed `Exception()` in two levels of subclasses... `__module__` doesn't do anything if you put in the parent (base) Exception() sub-class... it worked perfectly when I put it in the lowest child sub-classes... – Mike Pennington Oct 30 '20 at 22:34
5

I am not sure why you want to remove __main__ because that is the module name and when your exception would be in a appropriately named module, it would look beautiful not ugly e.g. myexceptions.BadException

Alternatively you can catch exception and print as you wish.

But if you want the uncaught exceptions to be printed as per your wish, try to set sys.excepthook e.g.

class BadThings(Exception): pass 

import traceback
def myexcepthook(type, value, tb):
    l = ''.join(traceback.format_exception(type, value, tb))
    print l

import sys
sys.excepthook = myexcepthook

raise BadThings("bad bad")

Output:

Traceback (most recent call last):
  File "untitled-1.py", line 12, in <module>
    raise BadThings("bad bad")
BadThings: bad bad

So in sys.excepthook you can modify exception, format it etc

Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219
  • 1
    I was just thinking from an end-user standpoint. They might not understand __main__., but I didn't know that it would print the module name, that is better, but they wouldn't understand that either. I see what you mean about catching the exceptions. I like your solution final above as it teaches me more about what is going on "behind the scenes." – narnie Sep 11 '10 at 17:55
1

If you handle the exception, you can format the message any way you like:

>>> try:
...     raise BadThings("This is really, really bad")
... except BadThings, e:
...     print e.msg
... 
This is really, really bad
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
-1

This is a slight modification of @Anurag's answer.

If you want to get rid of the __main__. AND the traceback, you can do something like this:

import sys
import traceback

class BadThings(Exception):
    def myexcepthook(type, value, tb):
        msg = ''.join(traceback.format_exception_only(type, value))
        print(msg)

    sys.excepthook = myexcepthook

raise BadThings("This is really, really bad")

Output:

BadThings: This is really, really bad

An added benefit of defining sys.excepthook in the exception class is that it won't override all exceptions, just BadThings.

Adam Stewart
  • 2,001
  • 1
  • 16
  • 16
  • *"An added benefit of defining `sys.excepthook` in the exception class is that it won't override all exceptions, just `BadThings`."* -- That's incorrect. Did you try it? Swap `raise BadThings` for `raise Exception` in the example and see what happens. The problem is that `sys` is outside the class; you just happen to be modifying it in the class body. – wjandrea Jan 01 '22 at 05:57