Comment imprimer le plein de sperme sans arrêter le programme?
Je suis en train d'écrire un programme qui analyse les 10 sites internet, qui localise les fichiers de données, enregistre les fichiers, puis analyse pour rendre les données qui peuvent être facilement utilisés dans la bibliothèque NumPy. Il y a tonnes des erreurs de ce fichier des rencontres par le biais de mauvais liens, mal formé XML, des entrées manquantes, et d'autres choses que j'ai encore à catégoriser. J'ai d'abord fait ce programme pour gérer les erreurs de ce type:
try:
do_stuff()
except:
pass
Mais maintenant je veux le journal des erreurs:
try:
do_stuff()
except Exception, err:
print Exception, err
Remarque c'est l'impression dans un fichier journal pour l'examiner plus tard. Ce imprime généralement très de données inutiles. Ce que je veux, c'est d'imprimer exactement les mêmes lignes imprimées lorsque l'erreur, déclenche sans l'essayer-à l'exception de l'interception de l'exception, mais je n'en veux pas à arrêter mon programme car elle est imbriquée dans une série de boucles que j'aimerais voir à la fin.
Vous devez vous connecter pour publier un commentaire.
Une autre réponse ont déjà souligné le traceback module.
Veuillez noter qu'avec
print_exc
, dans certains cas du coin, vous ne serez pas obtenir ce que vous attendez. En Python 2.x:...affiche la traçabilité en amont de la dernier exception:
Si vous avez vraiment besoin d'accéder à l'original traceback une solution consiste à mettre en cache les exception d'infos retourné à partir de
exc_info
dans une variable et de l'afficher à l'aide deprint_exception
:Production:
Quelques pièges à cela:
De la doc de
sys_info
:mais, à partir de la même doc:
D'autre part, en vous permettant d'accéder à la traçabilité en amont associés à une exception, Python 3 produire moins un résultat surprenant:
... afficher:
traceback.format_exc()
ousys.exc_info()
donnera plus d'info si c'est ce que vous voulez.print(sys.exc_info()[0]
imprime<class 'Exception'>
.Si vous êtes le débogage et vous voulez juste pour voir la trace de la pile, vous pouvez simplement appeler:
traceback.print_stack()
Il n'y a pas besoin d'augmenter manuellement une exception juste pour l'attraper à nouveau.
Lorsque vous ne voulez pas interrompre votre programme sur une erreur, vous avez besoin pour gérer cette erreur avec un try/except:
Pour extraire le plein de sperme, nous allons utiliser le
traceback
module de la bibliothèque standard:Et de créer un décemment compliqué stacktrace de démontrer que nous obtenir le plein stacktrace:
Impression
À impression le plein de sperme, utilisez le
traceback.print_exc
méthode:Qui imprime:
Mieux que l'impression, l'enregistrement:
Cependant, une bonne pratique est d'avoir un enregistreur pour votre module. Il connaîtra le nom du module et être en mesure de modifier les niveaux (entre autres attributs, tels que les gestionnaires d')
Dans ce cas, vous aurez besoin de la
logger.exception
fonction de la place:Qui enregistre le:
Ou peut-être vous voulez juste la chaîne, dans ce cas, vous aurez besoin de la
traceback.format_exc
fonction de la place:Qui enregistre le:
Conclusion
Et pour les trois options, nous voyons que nous obtenir le même résultat que lorsque nous avons une erreur:
traceback.print_exc()
retourne uniquement le dernier appel : comment avez-vous réussi à revenir plusieurs niveau de la pile (et éventuellement tous levele s?)raise
ou de l'exception de chaînage, ou vous vous cachez l'origine de sperme? voir stackoverflow.com/questions/2052390/...Tout d'abord, ne pas utiliser
print
s pour l'enregistrement, il est astable, prouvée et bien pensé stdlib module pour faire ça:journalisation
. Vous avez certainement devrait l'utiliser à la place.Deuxièmement, ne pas être tenté de faire un mess sans rapport avec les outils de quand il est originaire et simple d'approche. Ici, il est:
Que c'est. Vous êtes maintenant.
Explication pour n'importe qui qui est intéressé par la façon dont les choses fonctionnent sous le capot
Ce
log.exception
est en train de faire est juste un appel àlog.error
(qui est, le journal de l'événement avec le niveauERROR
) et impression traceback ensuite.Pourquoi est-il mieux?
Eh bien, voici quelques considérations:
Pourquoi personne ne s'est
traceback
ou appeler enregistreur avecexc_info=True
ou salir les mains avecsys.exc_info
?Bien, tout simplement parce que! Ils existent tous à des fins différentes. Par exemple,
traceback.print_exc
's la sortie est un peu différent de retraçage produite par l'interprète lui-même. Si vous l'utilisez, vous confondez quiconque lit les journaux, ils vont être frapper leurs têtes contre eux.Passant
exc_info=True
pour les appels du journal est tout simplement inapproprié. Mais, il est utile lors de la capture de recouvrable des erreurs et que vous voulez vous connecter (en utilisant, e.gINFO
niveau) avec un retraçage en tant que bien, parce quelog.exception
produit des rapports d'un seul niveau -ERROR
.Et vous avez certainement devraient éviter de jouer avec
sys.exc_info
autant que vous le pouvez. Il est tout simplement pas une interface publique, c'est de l'intérieur, vous peut l'utiliser si vous savez certainement ce que vous faites. Il n'est pas prévu pour l'impression des exceptions.logging.exception()
. Pas besoin de créer une instance de journal, sauf si vous avez des exigences particulières.En plus de @Aaron Hall de la réponse, si vous vous connectez, mais ne voulez pas utiliser
logging.exception()
(car il se connecte sur le niveau d'ERREUR), vous pouvez utiliser un niveau inférieur et passerexc_info=True
. par exemple,Pour obtenir le précis trace de la pile, comme une chaîne de caractères, que serait ont été soulevées si aucun try/except étaient là pour l'étape au-dessus, il suffit de le placer dans le bloc except que les captures de la délinquance exception.
Voici comment l'utiliser (en supposant que
flaky_func
est défini, etlog
appels préférée de votre système de journalisation):C'est une bonne idée de les attraper et de les re-raise
KeyboardInterrupt
s, de sorte que vous pouvez toujours arrêter le programme à l'aide de Ctrl-C. la Journalisation est en dehors de la portée de la question, mais une bonne option est la journalisation. La Documentation pour la sys et traceback modules.desired_trace = traceback.format_exc()
. En passantsys.exc_info()
que l'argument n'a jamais été la bonne chose à faire, mais obtient ignorées silencieusement en Python 2—mais pas dans Python 3 (3.6.4 de toute façon).KeyboardInterrupt
n'est pas dérivée (directement ou indirectement) de laException
. (Les deux sont dérivés deBaseException
.) Cela signifieexcept Exception:
ne serez jamais attraper unKeyboardInterrupt
, et donc laexcept KeyboardInterrupt: raise
est complètement inutile.Vous aurez besoin de mettre de l'essayer, sauf à l'intérieur de la plupart des innerloop où l'erreur peut se produire, c'est à dire
... et ainsi de suite
En d'autres termes, vous aurez besoin d'envelopper les déclarations qui risquent de ne pas en try/except aussi précis que possible, dans le plus à l'intérieur de la boucle que possible.
Une remarque sur cette réponsecommentaires:
print(traceback.format_exc())
fait un meilleur travail pour moi quetraceback.print_exc()
. Avec ce dernier, lehello
est parfois étrangement "mixte" avec le traceback texte, comme si les deux veulent écrire sur la sortie standard stdout ou stderr dans le même temps, la production bizarre de sortie (au moins lors de la construction de l'intérieur d'un éditeur de texte et l'affichage de la sortie dans les "résultats" du panneau).Donc j'utilise:
Je ne la vois pas mentionnée dans aucune des autres réponses. Si vous êtes de passage autour d'un objet d'Exception pour quelque raison que ce soit...
En Python 3.5+, vous pouvez obtenir une trace à partir d'un objet d'Exception à l'aide de traceback.TracebackException.from_exception(). Par exemple:
Cependant, le code ci-dessus les résultats dans:
C'est juste les deux niveaux de la pile, par opposition à ce qui aurait été imprimé à l'écran a l'exception été soulevées dans le
stack_lvl_2()
et ne sont pas interceptées (décommentez la# raise
ligne).Ce que je comprends, c'est parce qu'une exception n'enregistre que le niveau actuel de la pile lorsqu'il est soulevé,
stack_lvl_3()
dans ce cas. Comme il est passé par la pile, plus les niveaux sont ajoutés à ses__traceback__
. Mais nous avons intercepté dansstack_lvl_2()
, tous les sens il y a eu un record a été de niveaux 3 et 2. Pour obtenir le plein de trace imprimée sur stdout nous aurions de l'attraper le plus élevé (plus bas?) niveau:Qui se traduit par:
Avis que la pile d'impression est différente, la première et la dernière lignes sont manquantes. Parce que c'est un différents
format()
.Intercepter l'exception d'aussi loin du point où il a été soulevé que possible pour simplifier le code tout en donnant plus d'informations.
Vous voulez le traceback module. Il vous permettra d'imprimer les vidages de pile comme le Python fait normalement. En particulier, la print_last fonction d'impression de la dernière exception et une trace de la pile.
Obtenir le plein de sperme comme une chaîne de caractères de l'objet de l'exception avec
traceback.format_exception
Si vous avez seulement un objet d'exception, vous pouvez obtenir le traceback comme une chaîne de caractères à partir de n'importe quel point du code en Python 3 avec:
Exemple complet:
De sortie:
Documentation: https://docs.python.org/3.7/library/traceback.html#traceback.format_exception
Voir aussi: Extrait de l'exī info à partir d'un objet d'exception
Testé en Python 3.7.3.
Si vous avez une Erreur de l'objet déjà, et que vous souhaitez imprimer l'ensemble de la chose, vous avez besoin de faire un peu maladroit appel:
C'est vrai,
print_exception
prend trois les arguments de position: Le type de l'exception, à l'exception de l'objet, et à l'exception internes propres à assurer la traçabilité de la propriété.En python 3.5 ou ultérieure, la
type(err)
est facultatif... mais c'est une position d'argument, donc vous avez encore à transmettre explicitement Aucun à sa place.Je n'ai aucune idée de pourquoi ce n'est pas seulement
traceback.print_exception(err)
. Pourquoi vouloir imprimer une erreur, avec un traceback autre que celui qui appartient à cette erreur, est au delà de moi.