226 votes

Comment enregistrer mon erreur de traçage?

J'ai essayé de faire en sorte que cela fonctionne, mais pour une raison quelconque, cela me donne des erreurs ...

Comment enregistrer mes erreurs python?

 try:
    pass #CODE HERE
except:
    pass #LOG TRACEBACK ERROR ...whatever that error may be
 

313voto

nosklo Points 75862
 import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)

logging.debug('This message should go to the log file')

try:
   run_my_stuff()
except:
   logging.exception('Got exception on main handler')
   raise
 

En regardant maintenant le fichier journal, /tmp/logging_example.out :

 DEBUG:root:This message should go to the log file
ERROR:root:Got exception on main handler
Traceback (most recent call last):
  File "/tmp/teste.py", line 9, in <module>
    run_my_stuff()
NameError: name 'run_my_stuff' is not defined
 

76voto

Brad Barrows Points 613

Mon travail a récemment chargé de me connecter tous les retraçage/exceptions à partir de notre application. J'ai essayé de nombreuses techniques que d'autres avaient mis en ligne tel que celui ci-dessus, il s'installe sur une approche différente. Primordial traceback.print_exception.

J'ai une écriture à http://www.bbarrows.com/ ce serait beaucoup plus facile à lire, mais Malade de le coller dans ici.

Lorsqu'ils sont chargés d'enregistrer toutes les exceptions que notre logiciel peut rencontrer dans la nature, j'ai essayé un certain nombre de techniques différentes pour vous connecter à notre python exception retraçage. Au début, je pensais que le python exception système de crochet, sys.excepthook serait l'endroit idéal pour insérer le code d'enregistrement. J'ai essayé quelque chose de similaire à:

import traceback
import StringIO
import logging
import os, sys

def my_excepthook(excType, excValue, traceback, logger=logger):
    logger.error("Logging an uncaught exception",
                 exc_info=(excType, excValue, traceback))

sys.excepthook = my_excepthook  

Il a travaillé pour le thread principal, mais j'ai vite constaté que le mon sys.excepthook n'existerait pas sur tous les nouveaux threads mon processus a commencé. C'est un énorme problème parce que la plupart de tout ce qui se passe dans les fils dans ce projet.

Après une recherche sur google et lire beaucoup de documentation renseignements les plus utiles que j'ai trouvé était de l'Python bug tracker.

Le premier post sur le thread montre un exemple de travail de l' sys.excepthook PAS de persistance dans les threads (voir ci-dessous). Apparemment, c'est le comportement attendu.

import sys, threading

def log_exception(*args):
    print 'got exception %s' % (args,)
sys.excepthook = log_exception

def foo():
    a = 1 / 0

threading.Thread(target=foo).start()

Les messages sur ce Python Problème de thread vraiment de résultat dans les 2 a suggéré de hacks. Soit la sous-classe Thread et envelopper la méthode run dans notre propre essayer à l'exception de bloc dans le but de les attraper et de les consigner les exceptions ou monkey patch threading.Thread.run à exécuter dans votre propre essayer à l'exception de bloquer les journaux et les exceptions.

La première méthode de sous-classement d' Thread me semble être moins élégant dans votre code que vous auriez à l'importation et l'utilisation de votre coutume Thread de la classe PARTOUT où vous voulais avoir un thread de journalisation. Cela a fini par être embêtant car j'ai dû chercher l'intégralité de notre base de code et de le remplacer tout à fait normal Threads avec cette coutume Thread. Cependant, il était clair que ce Thread , et serait plus facile pour quelqu'un diagnostic et de débogage si quelque chose n'allait pas avec le custom logging code. Un custome thread de journalisation pourrait ressembler à ceci:

class TracebackLoggingThread(threading.Thread):
    def run(self):
        try:
            super(TracebackLoggingThread, self).run()
        except (KeyboardInterrupt, SystemExit):
            raise
        except Exception, e:
            logger = logging.getLogger('')
            logger.exception("Logging an uncaught exception")

La deuxième méthode de monkey patching threading.Thread.run est agréable parce que je pouvais juste l'exécuter une fois à droite après l' __main__ et l'instrument de mon code d'enregistrement dans toutes les exceptions. Monkey patching peut être gênant pour déboguer bien que l'évolution de la fonctionnalité attendue de quelque chose. L'proposé un patch à partir de l'Python outil de suivi a été:

def installThreadExcepthook():
    """
    Workaround for sys.excepthook thread bug
    From
http://spyced.blogspot.com/2007/06/workaround-for-sysexcepthook-bug.html

(https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1230540&group_id=5470).
    Call once from __main__ before creating any threads.
    If using psyco, call psyco.cannotcompile(threading.Thread.run)
    since this replaces a new-style class method.
    """
    init_old = threading.Thread.__init__
    def init(self, *args, **kwargs):
        init_old(self, *args, **kwargs)
        run_old = self.run
        def run_with_except_hook(*args, **kw):
            try:
                run_old(*args, **kw)
            except (KeyboardInterrupt, SystemExit):
                raise
            except:
                sys.excepthook(*sys.exc_info())
        self.run = run_with_except_hook
    threading.Thread.__init__ = init

Il n'était pas jusqu'à ce que j'ai commencé à tester mes enregistrement d'exception, j'ai réalisé que j'étais dans l'erreur.

Pour tester j'avais placé un

raise Exception("Test")

quelque part dans mon code. Cependant, l'enveloppant d'une méthode qui a appelé cette méthode a été d'essayer sauf bloc imprimé assurer la traçabilité et d'ingestion de l'exception. C'était très frustrant parce que j'ai vu le traceback apporter affichée sur la sortie standard, mais n'étant pas connecté. Il a été ensuite, j'ai décidé que la méthode la plus simple de l'enregistrement de l'retraçage était juste pour monkey patch la méthode que tous les code python utilise pour imprimer le retraçage eux-mêmes, traceback.print_exception. Je me suis retrouvé avec quelque chose de similaire à la suivante:

def add_custom_print_exception():
    old_print_exception = traceback.print_exception
    def custom_print_exception(etype, value, tb, limit=None, file=None):
        tb_output = StringIO.StringIO()
        traceback.print_tb(tb, limit, tb_output)
        logger = logging.getLogger('customLogger')
        logger.error(tb_output.getvalue())
        tb_output.close()
        old_print_exception(etype, value, tb, limit=None, file=None)
    traceback.print_exception = custom_print_exception

Ce code écrit le traceback à un Tampon de Chaîne et les journaux à la journalisation des ERREURS. J'ai un custom logging gestionnaire a mis sur pied la customLogger' enregistreur qui prend le niveau d'ERREUR de journaux et de les envoyer à la maison pour l'analyse.

0voto

Hugo Walter Points 502

peut-être pas aussi élégant, mais plus facile:

 #!/bin/bash
log="/var/log/yourlog"
/path/to/your/script.py 2>&1 | (while read; do echo "$REPLY" >> $log; done)
 

-3voto

rogeriopvl Points 9619

Voici un exemple simple tiré de la documentation de Python 2.6 :

 import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)

logging.debug('This message should go to the log file')
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X