How to get the name of an exception that was caught in Python?
Question:
How can I get the name of an exception that was raised in Python?
e.g.,
try:
foo = bar
except Exception as exception:
name_of_exception = ???
assert name_of_exception == 'NameError'
print "Failed with exception [%s]" % name_of_exception
For example, I am catching multiple (or all) exceptions, and want to print the name of the exception in an error message.
Answers:
This works, but it seems like there must be an easier, more direct way?
try:
foo = bar
except Exception as exception:
assert repr(exception) == '''NameError("name 'bar' is not defined",)'''
name = repr(exception).split('(')[0]
assert name == 'NameError'
Here are a few different ways to get the name of the class of the exception:
type(exception).__name__
exception.__class__.__name__
exception.__class__.__qualname__
e.g.,
try:
foo = bar
except Exception as exception:
assert type(exception).__name__ == 'NameError'
assert exception.__class__.__name__ == 'NameError'
assert exception.__class__.__qualname__ == 'NameError'
You can also use sys.exc_info()
. exc_info()
returns 3 values: type, value, traceback. On documentation: https://docs.python.org/3/library/sys.html#sys.exc_info
import sys
try:
foo = bar
except Exception:
exc_type, value, traceback = sys.exc_info()
assert exc_type.__name__ == 'NameError'
print "Failed with exception [%s]" % exc_type.__name__
If you want the fully qualified class name (e.g. sqlalchemy.exc.IntegrityError
instead of just IntegrityError
), you can use the function below, which I took from MB’s awesome answer to another question (I just renamed some variables to suit my tastes):
def get_full_class_name(obj):
module = obj.__class__.__module__
if module is None or module == str.__class__.__module__:
return obj.__class__.__name__
return module + '.' + obj.__class__.__name__
Example:
try:
# <do something with sqlalchemy that angers the database>
except sqlalchemy.exc.SQLAlchemyError as e:
print(get_full_class_name(e))
# sqlalchemy.exc.IntegrityError
The other answers here are great for exploration purposes, but if the primary goal is to log the exception (including the name of the exception), perhaps consider using logging.exception instead of print?
You can print the exception using some formated strings:
Example:
try:
#Code to execute
except Exception as err:
print(f"{type(err).__name__} was raised: {err}")
When you say "name" this could mean a couple of things: it could mean only the "immediate" classname, or it could mean the fully qualified name. Usually the latter will be much more useful and less error-prone: I’ve come across more than one case of 2 or more types with same "immediate" classname but from different packages.
If you want to print or log the fully qualified name this is one of the simplest things to do:
try:
do_something()
except BaseException as e:
logger.error(f'whoops! {type(e)}: {e}')
# or maybe
print(f'whoops! {type(e)}: {e}', file=sys.stderr)
The fully qualified classname will then be printed out like this: "<class ‘json.decoder.JSONDecodeError’>", and then be followed by the exception message. The OP says he wants "for example", to print a message, so assert
statements as in the chosen answer don’t seem to be called for.
The answer by MrName is also not irrelevant, and does make a sensible suggestion! if in the above you replaced logger.error(...)
with logger.exception('whoops!')
(NB a user message is a required param) you’d get your exception’s fully qualified name logged, not to mention its message, and a stack trace for free.
PS as suggested by the name, JSONDecodeError
in my example is an Error
, not an Exception
(it is a subclass of ValueError
). Catching BaseException
(the superclass of both Error
and Exception
) usually makes life easier when you’re not fishing for a specific exception. The OP says he wants to catch "all" exceptions.
How can I get the name of an exception that was raised in Python?
e.g.,
try:
foo = bar
except Exception as exception:
name_of_exception = ???
assert name_of_exception == 'NameError'
print "Failed with exception [%s]" % name_of_exception
For example, I am catching multiple (or all) exceptions, and want to print the name of the exception in an error message.
This works, but it seems like there must be an easier, more direct way?
try:
foo = bar
except Exception as exception:
assert repr(exception) == '''NameError("name 'bar' is not defined",)'''
name = repr(exception).split('(')[0]
assert name == 'NameError'
Here are a few different ways to get the name of the class of the exception:
type(exception).__name__
exception.__class__.__name__
exception.__class__.__qualname__
e.g.,
try:
foo = bar
except Exception as exception:
assert type(exception).__name__ == 'NameError'
assert exception.__class__.__name__ == 'NameError'
assert exception.__class__.__qualname__ == 'NameError'
You can also use sys.exc_info()
. exc_info()
returns 3 values: type, value, traceback. On documentation: https://docs.python.org/3/library/sys.html#sys.exc_info
import sys
try:
foo = bar
except Exception:
exc_type, value, traceback = sys.exc_info()
assert exc_type.__name__ == 'NameError'
print "Failed with exception [%s]" % exc_type.__name__
If you want the fully qualified class name (e.g. sqlalchemy.exc.IntegrityError
instead of just IntegrityError
), you can use the function below, which I took from MB’s awesome answer to another question (I just renamed some variables to suit my tastes):
def get_full_class_name(obj):
module = obj.__class__.__module__
if module is None or module == str.__class__.__module__:
return obj.__class__.__name__
return module + '.' + obj.__class__.__name__
Example:
try:
# <do something with sqlalchemy that angers the database>
except sqlalchemy.exc.SQLAlchemyError as e:
print(get_full_class_name(e))
# sqlalchemy.exc.IntegrityError
The other answers here are great for exploration purposes, but if the primary goal is to log the exception (including the name of the exception), perhaps consider using logging.exception instead of print?
You can print the exception using some formated strings:
Example:
try:
#Code to execute
except Exception as err:
print(f"{type(err).__name__} was raised: {err}")
When you say "name" this could mean a couple of things: it could mean only the "immediate" classname, or it could mean the fully qualified name. Usually the latter will be much more useful and less error-prone: I’ve come across more than one case of 2 or more types with same "immediate" classname but from different packages.
If you want to print or log the fully qualified name this is one of the simplest things to do:
try:
do_something()
except BaseException as e:
logger.error(f'whoops! {type(e)}: {e}')
# or maybe
print(f'whoops! {type(e)}: {e}', file=sys.stderr)
The fully qualified classname will then be printed out like this: "<class ‘json.decoder.JSONDecodeError’>", and then be followed by the exception message. The OP says he wants "for example", to print a message, so assert
statements as in the chosen answer don’t seem to be called for.
The answer by MrName is also not irrelevant, and does make a sensible suggestion! if in the above you replaced logger.error(...)
with logger.exception('whoops!')
(NB a user message is a required param) you’d get your exception’s fully qualified name logged, not to mention its message, and a stack trace for free.
PS as suggested by the name, JSONDecodeError
in my example is an Error
, not an Exception
(it is a subclass of ValueError
). Catching BaseException
(the superclass of both Error
and Exception
) usually makes life easier when you’re not fishing for a specific exception. The OP says he wants to catch "all" exceptions.