pythonexceptionmessage

How do I raise the same Exception with a custom message in Python?


I have this try block in my code:

try:
    do_something_that_might_raise_an_exception()
except ValueError as err:
    errmsg = 'My custom error message.'
    raise ValueError(errmsg)

Strictly speaking, I am actually raising another ValueError, not the ValueError thrown by do_something...(), which is referred to as err in this case. How do I attach a custom message to err? I try the following code but fails due to err, a ValueError instance, not being callable:

try:
    do_something_that_might_raise_an_exception()
except ValueError as err:
    errmsg = 'My custom error message.'
    raise err(errmsg)

Solution

  • If you're lucky enough to only support python 3.x, this really becomes a thing of beauty :)

    raise from

    We can chain the exceptions using raise from.

    try:
        1 / 0
    except ZeroDivisionError as e:
        raise Exception('Smelly socks') from e
    

    In this case, the exception your caller would catch has the line number of the place where we raise our exception.

    Traceback (most recent call last):
      File "test.py", line 2, in <module>
        1 / 0
    ZeroDivisionError: division by zero
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "test.py", line 4, in <module>
        raise Exception('Smelly socks') from e
    Exception: Smelly socks
    

    Notice the bottom exception only has the stacktrace from where we raised our exception. Your caller could still get the original exception by accessing the __cause__ attribute of the exception they catch.

    with_traceback

    Or you can use with_traceback.

    try:
        1 / 0
    except ZeroDivisionError as e:
        raise Exception('Smelly socks').with_traceback(e.__traceback__)
    

    Using this form, the exception your caller would catch has the traceback from where the original error occurred.

    Traceback (most recent call last):
      File "test.py", line 2, in <module>
        1 / 0
    ZeroDivisionError: division by zero
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "test.py", line 4, in <module>
        raise Exception('Smelly socks').with_traceback(e.__traceback__)
      File "test.py", line 2, in <module>
        1 / 0
    Exception: Smelly socks
    

    Notice the bottom exception has the line where we performed the invalid division as well as the line where we reraise the exception.