Default message in custom exception – Python
Question:
I want to create a custom exception in Python, that when raised without any arguments, it will print a default message.
Code Example:
class CustomException(Exception):
pass # some code
raise CustomException()
and get the below output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.CustomException: This is a default message!
Answers:
The solution is given by the bellow code:
class CustomException(Exception):
def __init__(self, *args, **kwargs):
default_message = 'This is a default message!'
# if any arguments are passed...
# If you inherit from the exception that takes message as a keyword
# maybe you will need to check kwargs here
if args:
# ... pass them to the super constructor
super().__init__(*args, **kwargs)
else: # else, the exception was raised without arguments ...
# ... pass the default message to the super constructor
super().__init__(default_message, **kwargs)
An equivalent but more succinct solution is:
class CustomException(Exception):
def __init__(self, *args, **kwargs):
default_message = 'This is a default message!'
# if no arguments are passed set the first positional argument
# to be the default message. To do that, we have to replace the
# 'args' tuple with another one, that will only contain the message.
# (we cannot do an assignment since tuples are immutable)
# If you inherit from the exception that takes message as a keyword
# maybe you will need to check kwargs here
if not args: args = (default_message,)
# Call super constructor
super().__init__(*args, **kwargs)
An even more succinct but restricted solution, in a way that you can only raise the CustomException with no arguments is:
class CustomException(Exception):
def __init__(self):
default_message = 'This is a default message!'
super().__init__(default_message)
You can of course save one line, in each of the above solutions, if you just pass the string literal to the constructor rather than using the default_message
variable.
If you want the code to be Python 2.7 compatible, then you just replace the: super()
with super(CustomException, self)
.
Now running:
>>> raise CustomException
will output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.CustomException: This is a default message!
and running:
raise CustomException('This is a custom message!')
will output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.CustomException: This is a custom message!
This is the output that the first 2 solutions’ code will produce. The last solution, differs in that calling it with at least one argument, like:
raise CustomException('This is a custom message!')
it will output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes 1 positional argument but 2 were given
because it does not permit any arguments to be passed to the CustomException when it is raised.
This is the simplest solution IMHO how to define custom exception with a default message that can be overridden if needed:
class CustomException(Exception):
def __init__(self, msg='My default message', *args, **kwargs):
super().__init__(msg, *args, **kwargs)
Usage example:
In [10]: raise CustomException
---------------------------------------------------------------------------
CustomException Traceback (most recent call last)
<ipython-input-10-259ae5202c8e> in <module>
----> 1 raise CustomException
CustomException: My default message
In [11]: raise CustomException()
---------------------------------------------------------------------------
CustomException Traceback (most recent call last)
<ipython-input-11-c1921a8781a6> in <module>
----> 1 raise CustomException()
CustomException: My default message
In [12]: raise CustomException('Foo bar')
---------------------------------------------------------------------------
CustomException Traceback (most recent call last)
<ipython-input-12-7efbf94f7432> in <module>
----> 1 raise CustomException('Foo bar')
CustomException: Foo bar
As regarded in an answer to this question, this is a pretty good way to declare a custom exception:
class MyException(Exception):
"""Docstring here"""
If one has many exceptions to define, one may use a subclass of Exception
as their exceptions’ superclass to make these exceptions’ docstrings their default messages:
class DocDefaultException(Exception):
"""Subclass exceptions use docstring as default message"""
def __init__(self, msg=None, *args, **kwargs):
super().__init__(msg or self.__doc__, *args, **kwargs)
class MyException(DocDefaultException):
"""Docstring here."""
raise MyException
Output:
Traceback (most recent call last):
File "C:************************.py", line 9, in <module>
raise MyException
__main__.MyException: Docstring here
A decorator also works to use the docstring of a custom exception as its default message:
import functools
def docstring_message(cls):
"""Decorates an exception to make its docstring its default message."""
# Must use cls_init name, not cls.__init__ itself, in closure to avoid recursion
cls_init = cls.__init__
@functools.wraps(cls.__init__)
def wrapped_init(self, msg=cls.__doc__, *args, **kwargs):
cls_init(self, msg, *args, **kwargs)
cls.__init__ = wrapped_init
return cls
@docstring_message
class MyException(Exception):
"""Docstring here"""
raise MyException
Output:
Traceback (most recent call last):
File "C:************************.py", line 16, in <module>
raise MyException
__main__.MyException: Docstring here
Of course, one should raise exceptions with a descriptive message, but a default fallback is sufficient sometimes and a docstring can suffice if written correctly.
I want to create a custom exception in Python, that when raised without any arguments, it will print a default message.
Code Example:
class CustomException(Exception):
pass # some code
raise CustomException()
and get the below output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.CustomException: This is a default message!
The solution is given by the bellow code:
class CustomException(Exception):
def __init__(self, *args, **kwargs):
default_message = 'This is a default message!'
# if any arguments are passed...
# If you inherit from the exception that takes message as a keyword
# maybe you will need to check kwargs here
if args:
# ... pass them to the super constructor
super().__init__(*args, **kwargs)
else: # else, the exception was raised without arguments ...
# ... pass the default message to the super constructor
super().__init__(default_message, **kwargs)
An equivalent but more succinct solution is:
class CustomException(Exception):
def __init__(self, *args, **kwargs):
default_message = 'This is a default message!'
# if no arguments are passed set the first positional argument
# to be the default message. To do that, we have to replace the
# 'args' tuple with another one, that will only contain the message.
# (we cannot do an assignment since tuples are immutable)
# If you inherit from the exception that takes message as a keyword
# maybe you will need to check kwargs here
if not args: args = (default_message,)
# Call super constructor
super().__init__(*args, **kwargs)
An even more succinct but restricted solution, in a way that you can only raise the CustomException with no arguments is:
class CustomException(Exception):
def __init__(self):
default_message = 'This is a default message!'
super().__init__(default_message)
You can of course save one line, in each of the above solutions, if you just pass the string literal to the constructor rather than using the default_message
variable.
If you want the code to be Python 2.7 compatible, then you just replace the: super()
with super(CustomException, self)
.
Now running:
>>> raise CustomException
will output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.CustomException: This is a default message!
and running:
raise CustomException('This is a custom message!')
will output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.CustomException: This is a custom message!
This is the output that the first 2 solutions’ code will produce. The last solution, differs in that calling it with at least one argument, like:
raise CustomException('This is a custom message!')
it will output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes 1 positional argument but 2 were given
because it does not permit any arguments to be passed to the CustomException when it is raised.
This is the simplest solution IMHO how to define custom exception with a default message that can be overridden if needed:
class CustomException(Exception):
def __init__(self, msg='My default message', *args, **kwargs):
super().__init__(msg, *args, **kwargs)
Usage example:
In [10]: raise CustomException
---------------------------------------------------------------------------
CustomException Traceback (most recent call last)
<ipython-input-10-259ae5202c8e> in <module>
----> 1 raise CustomException
CustomException: My default message
In [11]: raise CustomException()
---------------------------------------------------------------------------
CustomException Traceback (most recent call last)
<ipython-input-11-c1921a8781a6> in <module>
----> 1 raise CustomException()
CustomException: My default message
In [12]: raise CustomException('Foo bar')
---------------------------------------------------------------------------
CustomException Traceback (most recent call last)
<ipython-input-12-7efbf94f7432> in <module>
----> 1 raise CustomException('Foo bar')
CustomException: Foo bar
As regarded in an answer to this question, this is a pretty good way to declare a custom exception:
class MyException(Exception):
"""Docstring here"""
If one has many exceptions to define, one may use a subclass of Exception
as their exceptions’ superclass to make these exceptions’ docstrings their default messages:
class DocDefaultException(Exception):
"""Subclass exceptions use docstring as default message"""
def __init__(self, msg=None, *args, **kwargs):
super().__init__(msg or self.__doc__, *args, **kwargs)
class MyException(DocDefaultException):
"""Docstring here."""
raise MyException
Output:
Traceback (most recent call last):
File "C:************************.py", line 9, in <module>
raise MyException
__main__.MyException: Docstring here
A decorator also works to use the docstring of a custom exception as its default message:
import functools
def docstring_message(cls):
"""Decorates an exception to make its docstring its default message."""
# Must use cls_init name, not cls.__init__ itself, in closure to avoid recursion
cls_init = cls.__init__
@functools.wraps(cls.__init__)
def wrapped_init(self, msg=cls.__doc__, *args, **kwargs):
cls_init(self, msg, *args, **kwargs)
cls.__init__ = wrapped_init
return cls
@docstring_message
class MyException(Exception):
"""Docstring here"""
raise MyException
Output:
Traceback (most recent call last):
File "C:************************.py", line 16, in <module>
raise MyException
__main__.MyException: Docstring here
Of course, one should raise exceptions with a descriptive message, but a default fallback is sufficient sometimes and a docstring can suffice if written correctly.