Comment obtenir le nom de l'exception qui a été capturée en Python?

122

Comment puis-je obtenir le nom d'une exception qui a été déclenchée en Python?

par exemple,

try:
    foo = bar
except Exception as exception:
    name_of_exception = ???
    assert name_of_exception == 'NameError'
    print "Failed with exception [%s]" % name_of_exception

Par exemple, j'attrape plusieurs exceptions (ou toutes) et je souhaite imprimer le nom de l'exception dans un message d'erreur.

Rob Bednark
la source
3
Pourquoi pensez-vous que vous en avez besoin? Pourquoi ne pas saisir une exception plus concrète (par exemple except NameError:) pour commencer?
7
J'ai quelques scénarios dans lesquels je veux attraper toutes les exceptions (ou une liste d'entre elles) et que je veux imprimer le nom de l'exception dans un message d'erreur.
Rob Bednark
1
Vous voudrez peut-être consulter le tracebackmodule de la bibliothèque standard , qui a des fonctions qui font un bon formatage des exceptions et des retraits.
Blckknght
1
@delnan cette situation se produit lorsque vous testez si une fonction lève une exception comme programmé
gokul_uf
J'avais besoin de quelque chose comme ça pour SÉCHER du code: plusieurs exceptions peuvent être déclenchées par la méthode que j'appelle, chacune étant gérée avec sa propre exceptinstruction, mais l'entrée de journal est très similaire dans chaque cas.
Adam Carroll

Réponses:

226

Voici quelques méthodes différentes pour obtenir le nom de la classe de l'exception:

  1. type(exception).__name__
  2. exception.__class__.__name__
  3. exception.__class__.__qualname__

par exemple,

try:
    foo = bar
except Exception as exception:
    assert type(exception).__name__ == 'NameError'
    assert exception.__class__.__name__ == 'NameError'
    assert exception.__class__.__qualname__ == 'NameError'
user1234
la source
6

Cela fonctionne, mais il semble qu'il doit y avoir un moyen plus simple et plus direct?

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
la source
4
Remplacez except Exception as exceptionpar le type d'exception que vous souhaitez attraper, c'est-à-dire except NameError as exception.
Maciej Gol
8
Je ne veux pas attraper des exceptions particulières connues à l'avance. Je veux attraper toutes les exceptions.
Rob Bednark
4

Vous pouvez également utiliser sys.exc_info(). exc_info()renvoie 3 valeurs: type, valeur, traceback. Sur la 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
la source
1

Si vous voulez le nom de classe complet (par exemple sqlalchemy.exc.IntegrityErrorau lieu de juste IntegrityError), vous pouvez utiliser la fonction ci-dessous, que j'ai tirée de la réponse impressionnante de MB à une autre question (j'ai simplement renommé certaines variables selon mes goûts):

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__

Exemple:

try:
    # <do something with sqlalchemy that angers the database>
except sqlalchemy.exc.SQLAlchemyError as e:
    print(get_full_class_name(e))

# sqlalchemy.exc.IntegrityError
MarredFromage
la source
1

Les autres réponses ici sont excellentes à des fins d'exploration, mais si l'objectif principal est de consigner l'exception (y compris le nom de l'exception), envisagez peut-être d'utiliser logging.exception au lieu de print?

MrName
la source