150

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.

Rob Bednark
  • 19,968
  • 18
  • 67
  • 100
  • 3
    *Why* do you think you need this? Why not catch a more concrete exception (e.g. `except NameError:`) to begin with? –  Aug 11 '13 at 21:07
  • 10
    I have a couple scenarios where I want to catch all exceptions (or a list of them), and want to print out the name of the exception in an error message. – Rob Bednark Aug 12 '13 at 07:04
  • 2
    You might want to check out the standard library's [`traceback`](https://docs.python.org/3/library/traceback.html) module, which has functions that do some nice formatting of exceptions and tracebacks. – Blckknght May 22 '14 at 23:16
  • 1
    @delnan this situation arises when you are testing if a function is raising an exception as programmed – gokul_uf Mar 14 '16 at 15:32
  • I needed something like this to DRY up some code: several exceptions can be raised by the method I'm calling, each are handled with their own `except` statement, but the log entry is very similar in each case. – Adam Carroll Oct 12 '17 at 16:01

5 Answers5

261

Here are a few different ways to get the name of the class of the exception:

  1. type(exception).__name__
  2. exception.__class__.__name__
  3. 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'
Acumenus
  • 41,481
  • 14
  • 116
  • 107
user1234
  • 5,520
  • 3
  • 25
  • 35
7

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__
moshfiqur
  • 1,717
  • 2
  • 19
  • 21
6

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'
Rob Bednark
  • 19,968
  • 18
  • 67
  • 100
  • 4
    Replace `except Exception as exception` with the type of exception you'd like to catch, i.e. `except NameError as exception`. – Maciej Gol Aug 11 '13 at 21:05
  • 15
    I don't want to catch particular exceptions known in advance. I want to catch *all* exceptions. – Rob Bednark Apr 27 '18 at 16:10
4

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
MarredCheese
  • 9,495
  • 5
  • 59
  • 63
0

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?

MrName
  • 1,887
  • 11
  • 23