IUissopretty
IUissopretty

Reputation: 81

Want my code to raise a specific type or error, but print the orginal error

So suppose I have some code that raises any type or error. I want my code instead to raise an AssertionError, but print out the original message of that would have been printed with the original error. How would I do that?

(example)

original error: TypeError: '>' not supported between instances of 'str' and 'int'

custom error: AssertionError: exception = TypeError: '>' not supported between instances of 'str' and 'int'

Upvotes: 3

Views: 688

Answers (3)

J_H
J_H

Reputation: 20450

You are looking for the from syntax (introduced in Python 3) that lets you wrap an app-specific exception around a base exception. Here is an example:

>>> try:
...     1 > '1'
... except TypeError as e:
...     raise AssertionError() from e
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: '>' not supported between instances of 'int' and 'str'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
AssertionError

You can supply a string containing a diagnostic message when you create a new exception. It would be better to define your own app-specific exception(s), rather than recycling AssertionError. If you define several, make one of them the [grand]parent and have other exceptions inherit from that ancestor. That allows callers to conveniently catch fine- or coarse-grained classes of errors.

There's a PEP that describes further considerations.

Upvotes: 3

sanyassh
sanyassh

Reputation: 8520

Also you can hide original traceback by setting __suppress_context__ = True and make some formatting to fit your needs of expected output:

try:
    a = '1' > 1
except Exception as exc:
    assertion_exc = AssertionError('exception = {}: {}'.format(type(exc).__name__, str(exc)))
    assertion_exc.__suppress_context__ = True # comment this line to see full traceback
    raise assertion_exc

Full output:

Traceback (most recent call last):
  File "./file.py", line 8, in <module>
    raise assertion_exc
AssertionError: exception = TypeError: '>' not supported between instances of 'str' and 'int'

Upvotes: 1

jcp
jcp

Reputation: 906

You'll have to catch the exception raised and then raise whichever type you'd like. Since you mentioned wanting to catch any type of error you would have to use the Exception class as your catch.

However, I would note that this is generally bad practice because you typically want to only catch specific errors that you anticipate having. But if you end up throwing an error anyways, i suppose its not terrible. But also make me wonder specifically what the goal of this code is. Anyways..

catch anything

try...except Exception as e

raise preferred error

raise AssertionError()

get the message

e.message

get the type

type(e)

Putting it all together:

try:
    # some code that raises an error
    g = 10 + '11'
except Exception as e:
    raise AssertionError('{}: {}'.format(type(e), e.message))

The output would be:

<type 'exceptions.TypeError'>: unsupported operand type(s) for +: 'int' and 'str'

This could be cleaned up to get rid of the ugly output of the type(e) but in general this is how you would include the type of error as well as its corresponding message.

Upvotes: 3

Related Questions