2010-06-25 3 views
39

Comment écrire une fonction de consignation de console personnalisée pour la sortie uniquement sur les messages de consignation de la fenêtre de la console sur une seule ligne (pas append) jusqu'au premier enregistrement de consignation standard.Comment écrire un gestionnaire de journalisation python personnalisé?

progress = ProgressConsoleHandler() 
console = logging.StreamHandler() 

logger = logging.getLogger('test') 
logger.setLevel(logging.DEBUG) 
logger.addHandler(console) 
logger.addHandler(progress) 

logger.info('test1') 
for i in range(3): 
    logger.progress('remaining %d seconds' % i) 
    time.sleep(1) 
logger.info('test2') 

Alors que la sortie de la console est seulement trois lignes:

INFO: test1 
remaining 0 seconds... 
INFO: test2 

Toutes les suggestions sur la meilleure façon sur la façon de mettre en œuvre ce?

+0

Où 'log' est-il défini? ... à part le 'log' dans' math' ... –

+0

La plupart de ceux-ci devraient aider: http://stackoverflow.com/search?q=python+logging+handler –

+0

duplication possible de [Rediriger la sortie de journalisation en utilisant la coutume gestionnaire de journalisation] (http://stackoverflow.com/questions/2819791/redirect-logging-output-using-custom-logging-handler) –

Répondre

45
import logging 
class ProgressConsoleHandler(logging.StreamHandler): 
    """ 
    A handler class which allows the cursor to stay on 
    one line for selected messages 
    """ 
    on_same_line = False 
    def emit(self, record): 
     try: 
      msg = self.format(record) 
      stream = self.stream 
      same_line = hasattr(record, 'same_line') 
      if self.on_same_line and not same_line: 
       stream.write(self.terminator) 
      stream.write(msg) 
      if same_line: 
       stream.write('... ') 
       self.on_same_line = True 
      else: 
       stream.write(self.terminator) 
       self.on_same_line = False 
      self.flush() 
     except (KeyboardInterrupt, SystemExit): 
      raise 
     except: 
      self.handleError(record) 
if __name__ == '__main__': 
    import time 
    progress = ProgressConsoleHandler() 
    console = logging.StreamHandler() 

    logger = logging.getLogger('test') 
    logger.setLevel(logging.DEBUG) 
    logger.addHandler(progress) 

    logger.info('test1') 
    for i in range(3): 
     logger.info('remaining %d seconds', i, extra={'same_line':True}) 
     time.sleep(1) 
    logger.info('test2') 

Notez que seul gestionnaire est enregistré, et l'argument de mot-clé extra pour que le gestionnaire le savent doit rester sur une ligne. Il y a plus de logique dans la méthode emit() pour gérer les changements entre les messages qui doivent rester sur une ligne et ceux qui doivent avoir leur propre ligne.

+9

FYI pour ceux qui rencontrent ceci: L'attribut 'terminator' est seulement disponible en Python> = 3.2, voir https://mail.python.org/pipermail/python-list/2010-October/590223.html – Pat

Questions connexes