max
max

Reputation: 52235

How to customize exception message

# python 3.5
>>> class MyError(Exception):
...   pass
...
>>> raise MyError('message')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.MyError: message

I want the exception to print just message instead of __main__.MyError: message. I tried defininig __str__ and __repr__ in both MyError itself and in its metaclass, but those had no effect. Where does python interpreter get __main__.MyError from?

Note that I can easily change how instances of MyError are printed, and how MyError itself is printed, but neither has any effect on the exception message:

class MyType(type):
  def __str__(self):
    return '***'

class MyError(Exception, metaclass=MyType):
  def __str__(self):
    return 'xxx'

print(MyError) # ***
print(MyError()) # xxx
raise MyError() # still the same

Upvotes: 4

Views: 776

Answers (2)

Fejs
Fejs

Reputation: 2888

The closest thing I could get is this:

In [6]: raise MyError("some message")
---------------------------------------------------------------------------
MyError                                   Traceback (most recent call last)
<ipython-input-2-4bd48c5b1ce0> in <module>()
----> 1 raise MyError("some error message")

MyError: some error message

There is a way to remove leading __main__. text in front of class name. There is even a way to remove class name itself, so output looks like this:

In [6]: raise MyError("some error message")
---------------------------------------------------------------------------
                                          Traceback (most recent call last)
<ipython-input-6-4bd48c5b1ce0> in <module>()
----> 1 raise MyError("some error message")

: some error message

However, I couldn't find a way to remove : sign. My guess is that this sign is generated by interpreter in order to clearly separate exception output from other output types.

Here's the solution I used:

class MyError(Exception):
    __module__ = None
    def __init__(self, *args, **kwargs):
        Exception.__init__(self, *args, **kwargs)
        self.__class__.__name__ = "CustomTextHere"

And some outputs:

In [8]: MyError
Out[8]: MyError

In [9]: MyError()
Out[9]: None.CustomTextHere()

In [11]: raise MyError()
---------------------------------------------------------------------------
CustomTextHere                            Traceback (most recent call last)
<ipython-input-11-f389ee70e588> in <module>()
----> 1 raise MyError()

CustomTextHere: 

In [12]: raise MyError("some error message")
---------------------------------------------------------------------------
CustomTextHere                            Traceback (most recent call last)
<ipython-input-12-4bd48c5b1ce0> in <module>()
----> 1 raise MyError("some error message")

CustomTextHere: some error message

If You want to get only : sign, you would use:

self.__class__.__name__ = ""

Upvotes: 2

Christopher Shroba
Christopher Shroba

Reputation: 7544

The first part of that line, before the colon, is the type of the Exception raised. It's in the same format as what's returned by:

>>> class MyError(Exception):
...     pass
...
>>> print(type(MyError("message")))
<class '__main__.MyError'>

Usually your custom exception class will be put inside some file (say, file.py), and imported, so in that case, it would be file.MyError isntead of __main__.MyError. However, since you're currently using an Exception defined in the main python file, the only namespace it has to use is __main__.

Long story short, if you want it to be prettier, put it in another file with the name you'd like.

Upvotes: 1

Related Questions