Obtenir la valeur d'exception en Python

239

Si j'ai ce code:

try:
    some_method()
except Exception, e:

Comment puis-je obtenir cette valeur d'exception (représentation de chaîne, je veux dire)?

Frias
la source

Réponses:

323

utilisation str

try:
    some_method()
except Exception as e:
    s = str(e)

De plus, la plupart des classes d'exception auront un argsattribut. Souvent, ce args[0]sera un message d'erreur.

Il convient de noter que le simple fait d'utiliser strrenverra une chaîne vide s'il n'y a pas de message d'erreur, tandis reprque l'utilisation recommandée par pyfunc affichera au moins la classe de l'exception. Mon avis est que si vous l'imprimez, c'est pour un utilisateur final qui ne se soucie pas de ce qu'est la classe et veut juste un message d'erreur.

Cela dépend vraiment de la classe d'exception que vous traitez et de la façon dont elle est instanciée. Aviez-vous quelque chose en particulier en tête?

aaronasterling
la source
J'imprime ceci pour faire un rapport, le str (e) est bien je suppose. Merci beaucoup
vendredi
8
Je préférerais l'utiliser e.messageparce args[0]que ce n'est peut-être pas vraiment un message.
cedbeu
3
repr (e) est également utile si vous souhaitez obtenir l'exception complète (par exemple NameError ("le nom global 'variable' n'est pas défini",), au lieu de "nom global 'variable' n'est pas défini"
Ben Morris
49
cette réponse est dangereuse, car elle échouera pour les exceptions unicode comme ceci: raise Exception(u'jörn'). L'échec est particulièrement grave, car vous ne verrez jamais l'exception réelle, mais juste un UnicodeDecodeError. Si vous ne connaissez pas le codage de l'exception (et la plupart du temps vous ne le savez pas), vous devriez soit travailler sur, repr(e)soit, si vous en avez vraiment besoin, utiliser un autre bloc try-except dans votre gestion des exceptions qui attrape UnicodeDecodeErrors et revient à repr(e).
Jörn Hees
11
D'accord avec @ JörnHees. Je ne peux pas compter le nombre de fois str(ou même unicodeou .format) qui a provoqué des bogues en raison de la gestion d'Unicode. Si vous n'avez pas le contrôle complet du contenu du message d'erreur, utilisez TOUJOURS reprpour éviter les erreurs Unicode inattendues.
Kenny Trytek
186

Utilisez repr () et La différence entre l'utilisation de repr et str

En utilisant repr:

>>> try:
...     print(x)
... except Exception as e:
...     print(repr(e))
... 
NameError("name 'x' is not defined")

En utilisant str:

>>> try:
...     print(x)
... except Exception as e:
...     print(str(e))
... 
name 'x' is not defined
pyfunc
la source
2
ah, represt grâce utile, il semble toute autre chose unicode, strcodant pour , ... peut soulever une exception en fonction de l'entrée. Pas tout à fait utile lorsque vous essayez de garder l'exception à regarder, mais exception-safeil semble que
reproche
2
C'est beaucoup mieux que toutes les str()solutions similaires, car cela inclut en fait le type d'exception. Avec str()je suis arrivé 'status'alors qu'avec repr()je suis arrivé KeyError('status')et j'étais comme « Aaaaah, maintenant je comprends l'erreur ».
jlh
27

Même si je me rends compte que c'est une vieille question, j'aimerais suggérer d'utiliser le tracebackmodule pour gérer la sortie des exceptions.

Utilisez traceback.print_exc()pour imprimer l'exception actuelle à l'erreur standard, tout comme elle serait imprimée si elle n'était pas interceptée, ou traceback.format_exc()pour obtenir la même sortie qu'une chaîne. Vous pouvez passer divers arguments à l'une de ces fonctions si vous souhaitez limiter la sortie ou rediriger l'impression vers un objet de type fichier.

Blckknght
la source
23

Une autre voie n'a pas encore été donnée:

try:
    1/0
except Exception, e:
    print e.message

Production:

integer division or modulo by zero

args[0] pourrait en fait ne pas être un message.

str(e)pourrait renvoyer la chaîne avec des guillemets environnants et éventuellement avec le début usi unicode:

'integer division or modulo by zero'

repr(e) donne la représentation d'exception complète qui n'est probablement pas ce que vous voulez:

"ZeroDivisionError('integer division or modulo by zero',)"

Éditer

Ma faute !!! Il semble que ce BaseException.message soit obsolète2.6 , enfin, il semble définitivement qu'il n'y a toujours pas de manière standardisée d'afficher les messages d'exception. Je suppose donc que le mieux est de faire face à e.argset en str(e)fonction de vos besoins (et éventuellemente.message - si la bibliothèque que vous utilisez dépend de ce mécanisme).

Par exemple, avec pygraphviz, e.messageest le seul moyen d'afficher correctement l'exception, en utilisant str(e)entourera le message avecu'' .

Mais avec MySQLdb, la bonne façon de récupérer le message est e.args[1]: e.messageest vide, et str(e)affichera'(ERR_CODE, "ERR_MSG")'

cedbeu
la source
0

Pour python2, il est préférable d'utiliser e.messagepour obtenir le message d'exception, cela évitera possible UnicodeDecodeError. Mais oui e.messagesera vide pour certaines sortes d'exceptions comme OSError, dans ce cas, nous pouvons ajouter un exc_info=Trueà notre fonction de journalisation pour ne pas manquer l'erreur.
Pour python3, je pense qu'il est sûr à utiliser str(e).

apporc
la source
0

Si vous ne connaissez pas le type / l'origine de l'erreur, vous pouvez essayer:

import sys
try:
    doSomethingWrongHere()
except:
    print('Error: {}'.format(sys.exc_info()[0]))

Mais soyez conscient, vous obtiendrez un avertissement pep8:

[W] PEP 8 (E722): do not use bare except
Kostanos
la source
0

Pour inspecter le message d'erreur et faire quelque chose avec lui (avec Python 3) ...

try:
    some_method()
except Exception as e:
    if {value} in e.args:
        {do something}
DanGoodrick
la source