web-dev-qa-db-fra.com

Comment obtenir un message d'exception dans Python correctement

Quel est le meilleur moyen d'obtenir les messages des exceptions à partir des composants de la bibliothèque standard en Python?

J'ai remarqué que dans certains cas, vous pouvez l'obtenir via le champ message comme ceci:

try:
  pass
except Exception as ex:
  print(ex.message)

mais dans certains cas (par exemple, en cas d'erreur de socket), vous devez faire quelque chose comme ceci:

try:
  pass
except socket.error as ex:
  print(ex)

Je me demandais s'il y avait un moyen standard de couvrir la plupart de ces situations?

61
FrozenHeart

Si vous regardez documentation des erreurs intégrées , vous verrez que la plupart des classes Exception affectent leur premier argument sous la forme d'un attribut message. Tous ne le font pas cependant.

Notamment, EnvironmentError (avec les sous-classes IOError et OSError) a un premier argument de errno, deuxième de strerror. Il n'y a pas de message... strerror est à peu près analogue à ce qui serait normalement un message.

Plus généralement, les sous-classes de Exception peuvent faire ce qu'elles veulent. Ils peuvent ou non avoir un attribut message. Les futurs Exceptions intégrés ne peuvent pas avoir d'attribut message. Toute sous-classe Exception importée de bibliothèques tierces ou d'un code utilisateur ne peut pas avoir d'attribut message.

Je pense que la bonne façon de gérer cela consiste à identifier les sous-classes Exception spécifiques que vous voulez intercepter, puis d'attraper celles-ci au lieu de tout avec un except Exception, puis d'utiliser les attributs définis par cette sous-classe, comme vous le souhaitez. vouloir.

Si vous devez print quelque chose, je pense que l'impression du Exception intercepté lui-même est susceptible de faire ce que vous voulez, qu'il ait ou non un attribut message.

Vous pouvez également vérifier l'attribut de message si vous le souhaitez, comme ceci, mais je ne le suggérerais pas vraiment car cela semble tout simplement compliqué:

try:
    pass
except Exception as e:
    # Just print(e) is cleaner and more likely what you want,
    # but if you insist on printing message specifically whenever possible...
    if hasattr(e, 'message'):
        print(e.message)
    else:
        print(e)
54
ArtOfWarfare

Pour améliorer la réponse fournie par @ artofwarfare , voici ce que je considère comme un moyen plus simple de vérifier l'attribut message et de l'imprimer ou d'imprimer l'objet Exception comme solution de secours. .

try:
    pass 
except Exception as e:
    print getattr(e, 'message', repr(e))

L'appel à repr est facultatif, mais je le trouve nécessaire dans certains cas d'utilisation.


Mise à jour # 1:

Après le commentaire de @ MadPhysicist , voici une preuve de la raison pour laquelle l'appel à repr pourrait être nécessaire. Essayez d’exécuter le code suivant dans votre interpréteur:

try:
    raise Exception 
except Exception as e:
    print(getattr(e, 'message', repr(e)))
    print(getattr(e, 'message', str(e)))

Mise à jour # 2:

Voici une démo avec des détails pour Python 2.7 et 3.5: https://Gist.github.com/takwas/3b7a6edddef783f2abddffda1439f5

16
acetakwas

J'ai eu le même problème. Je pense que la meilleure solution consiste à utiliser log.exception, qui affichera automatiquement la trace de la pile et le message d'erreur, tels que:

try:
    pass
    log.info('Success')
except:
    log.exception('Failed')
0
Bill Z