J'ai une fonction appelée par le programme principal:
try:
someFunction()
except:
print "exception happened!"
mais au milieu de l'exécution de la fonction, il lève une exception, donc il saute à la except
partie.
Comment puis-je voir exactement ce qui s'est passé dans le someFunction()
qui a provoqué l'exception?
except:
(sans nuraise
), sauf peut-être une fois par programme, et de préférence pas à ce moment-là.except
clauses, vous n'aurez pas besoin de vérifier le type d'exception, c'est ce qui est généralement fait pour agir en fonction d'un type d'exception spécifique.except
bloc, l'exception est disponible via lasys.exc_info()
fonction - Cette fonction renvoie un tuple de trois valeurs qui fournissent des informations sur l'exception qui est actuellement gérée.Réponses:
Les autres réponses indiquent toutes que vous ne devez pas intercepter les exceptions génériques, mais personne ne semble vouloir vous dire pourquoi, ce qui est essentiel pour comprendre quand vous pouvez enfreindre la "règle". Voici une explication. Fondamentalement, c'est pour que vous ne vous cachiez pas:
Donc, tant que vous prenez soin de ne rien faire de tout cela, il est normal d'attraper l'exception générique. Par exemple, vous pouvez fournir des informations sur l'exception à l'utilisateur d'une autre manière, comme:
Alors, comment intercepter l'exception générique? Il y a plusieurs façons. Si vous voulez juste l'objet d'exception, faites-le comme ceci:
Assurez- vous d'
message
être porté à l'attention de l'utilisateur d'une manière difficile à manquer! L'imprimer, comme illustré ci-dessus, peut ne pas être suffisant si le message est enterré dans de nombreux autres messages. Ne pas attirer l'attention des utilisateurs équivaut à avaler toutes les exceptions, et s'il y a une impression que vous auriez dû retirer après avoir lu les réponses sur cette page, c'est que ce n'est pas une bonne chose . La fin du bloc except avec uneraise
instruction résoudra le problème en relançant de manière transparente l'exception qui a été interceptée.La différence entre ce qui précède et l'utilisation juste
except:
sans aucun argument est double:except:
ne vous donne pas l'objet d'exception à inspecterSystemExit
,KeyboardInterrupt
etGeneratorExit
ne sont pas prises par le code ci-dessus, qui est généralement ce que vous voulez. Voir la hiérarchie des exceptions .Si vous voulez également la même trace de pile que vous obtenez si vous n'attrapez pas l'exception, vous pouvez l'obtenir comme ceci (toujours à l'intérieur de la clause except):
Si vous utilisez le
logging
module, vous pouvez imprimer l'exception dans le journal (avec un message) comme ceci:Si vous voulez creuser plus profondément et examiner la pile, regardez les variables etc., utilisez la
post_mortem
fonction dupdb
module à l'intérieur du bloc except:J'ai trouvé cette dernière méthode inestimable lors de la recherche de bugs.
la source
Obtenez le nom de la classe à laquelle appartient l'objet d'exception:
et l'utilisation de la fonction print_exc () imprimera également la trace de la pile qui est une information essentielle pour tout message d'erreur.
Comme ça:
Vous obtiendrez une sortie comme celle-ci:
Et après impression et analyse, le code peut décider de ne pas gérer d'exception et d'exécuter simplement
raise
:Production:
Et l'interprète imprime l'exception:
Après que
raise
l'exception d'origine continue de se propager plus haut dans la pile des appels. ( Méfiez-vous des pièges possibles ) Si vous soulevez une nouvelle exception, il se soucie d'une nouvelle trace de pile (plus courte).Production:
Remarquez comment traceback n'inclut pas la
calculate()
fonction de la ligne9
qui est à l'origine de l'exception d'originee
.la source
traceback.format_exc()
aussi biene.__class__.__name__
est-ce la même chose quetype(e).__name__
, comme le suggère la réponse ci-dessus?Vous ne devriez généralement pas intercepter toutes les exceptions possibles
try: ... except
car cela est trop large. Attrapez simplement ceux qui devraient arriver pour une raison quelconque. Si vous devez vraiment, par exemple si vous voulez en savoir plus sur un problème lors du débogage, vous devezla source
try: ... except Exception:
beaucoup de choses, par exemple l'utilisation de bibliothèques dépendantes du réseau ou une masseuse de données qui peut lui envoyer des trucs bizarres. Naturellement, j'ai également une journalisation appropriée. Ceci est crucial pour permettre au programme de continuer à fonctionner en cas d'une seule erreur dans les données d'entrée.smtplib
?Sauf si
somefunction
c'est une très mauvaise fonction héritée codée, vous ne devriez pas avoir besoin de ce que vous demandez.Utilisez plusieurs
except
clauses pour gérer de différentes manières différentes exceptions:Le point principal est que vous ne devez pas intercepter une exception générique, mais uniquement celles dont vous avez besoin. Je suis sûr que vous ne voulez pas masquer les erreurs ou les bugs inattendus.
la source
La plupart des réponses pointent vers la
except (…) as (…):
syntaxe (à juste titre) mais en même temps, personne ne veut parler d'un éléphant dans la pièce, où l'éléphant estsys.exc_info()
fonction. À partir de la documentation du module sys (c'est moi qui souligne):Je pense que le
sys.exc_info()
pourrait être considéré comme la réponse la plus directe à la question initiale de Comment savoir quel type d'exception s'est produit?la source
except
. Juste pour être complet,exctype, value = sys.exc_info()[:2]
vous dira le type d'exception qui peut ensuite être utilisé sur leexcept
.essayez: someFunction () sauf Exception, exc:
la source
exc.__class__.__name__
avait déjà été suggéré dans la réponse d'Alex - stackoverflow.com/a/9824060/95735Ces réponses conviennent très bien pour le débogage, mais pour tester l'exception par programme, elles
isinstance(e, SomeException)
peuvent être utiles, car elles testent également les sous-classes deSomeException
, afin que vous puissiez créer des fonctionnalités qui s'appliquent aux hiérarchies d'exceptions.la source
Voici comment je gère mes exceptions. L'idée est d'essayer de résoudre le problème si c'est facile, et d'ajouter plus tard une solution plus souhaitable si possible. Ne résolvez pas le problème dans le code qui génère l'exception, ou ce code perd la trace de l'algorithme d'origine, qui devrait être écrit au point. Cependant, transmettez les données nécessaires pour résoudre le problème et renvoyez un lambda au cas où vous ne pourriez pas résoudre le problème en dehors du code qui le génère.
Pour l'instant, comme je ne veux pas penser de manière tangible à l'objectif de mon application, je n'ai ajouté aucune solution compliquée. Mais à l'avenir, quand j'en saurai plus sur les solutions possibles (puisque l'application est plus conçue), je pourrais ajouter un dictionnaire de solutions indexées par
during
.Dans l'exemple illustré, une solution pourrait être de rechercher des données d'application stockées ailleurs, par exemple si le fichier «app.p» a été supprimé par erreur.
Pour l'instant, étant donné que l'écriture du gestionnaire d'exceptions n'est pas une idée intelligente (nous ne connaissons pas encore les meilleures façons de le résoudre, car la conception de l'application évoluera), nous renvoyons simplement la solution simple qui consiste à agir comme si nous étions en cours d'exécution l'application pour la première fois (dans ce cas).
la source
Pour ajouter à la réponse de Lauritz, j'ai créé un décorateur / wrapper pour la gestion des exceptions et les journaux de wrapper quel type d'exception s'est produit.
Cela peut être appelé sur une méthode de classe ou une fonction autonome avec le décorateur:
@general_function_handler
Voir mon blog sur pour l'exemple complet: http://ryaneirwin.wordpress.com/2014/05/31/python-decorators-and-exception-handling/
la source
Vous pouvez commencer comme recommandé par Lauritz, avec:
et juste pour
print ex
aimer:la source
L'exception réelle peut être capturée de la manière suivante:
Vous pouvez en savoir plus sur les exceptions à partir du didacticiel Python .
la source
Votre question est: "Comment puis-je voir exactement ce qui s'est passé dans la fonction someFunction () qui a provoqué l'exception?"
Il me semble que vous ne demandez pas comment gérer les exceptions imprévues dans le code de production (comme de nombreuses réponses le supposent), mais comment savoir ce qui cause une exception particulière pendant le développement.
Le moyen le plus simple consiste à utiliser un débogueur qui peut s'arrêter là où l'exception non interceptée se produit, de préférence ne pas quitter, afin que vous puissiez inspecter les variables. Par exemple, PyDev dans l'IDE open source Eclipse peut le faire. Pour activer cela dans Eclipse, ouvrez la perspective Débogage, sélectionnez
Manage Python Exception Breakpoints
dans leRun
menu et cochezSuspend on uncaught exceptions
.la source
Abstenez-vous simplement d'attraper l'exception et le traceback que Python imprime vous dira quelle exception s'est produite.
la source