2010-06-25 11 views
39

So schreiben Sie eine benutzerdefinierte Konsolenprotokollfunktion, um nur die Protokollmeldungen des Konsolenfensters in einer einzelnen Zeile (nicht anhängen) bis zum ersten regulären Protokolldatensatz auszugeben.Wie schreibe ich benutzerdefinierte Python-Logging-Handler?

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') 

Damit die Konsolenausgabe ist nur drei Zeilen:

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

Irgendwelche Vorschläge auf dem besten Weg, wie dies zu implementieren?

+0

Wo ist 'log' definiert? ... neben dem 'log' in' math' ... –

+0

Die meisten davon sollten helfen: http://stackoverflow.com/search?q=python+logging+handler –

+0

mögliche Duplikate von [Redirect Logging-Ausgabe mit benutzerdefinierten Logging-Handler] (http://stackoverflow.com/questions/2819791/redirect-logging-output-using-custom-logging-handler) –

Antwort

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') 

Beachten Sie, dass nur ein Handler registriert wird, und das extra Schlüsselwort-Argument die Handler zu lassen wissen, dass es auf einer Linie bleiben soll. Es gibt mehr Logik in der emit()-Methode, um Änderungen zwischen Nachrichten zu behandeln, die in einer Zeile bleiben sollten, und Nachrichten, die eine eigene Zeile haben müssen.

+9

FYI für diejenigen, die darauf stoßen: Das 'Terminator'-Attribut ist nur in Python> = verfügbar 3.2, siehe https://mail.python.org/pipermail/python-list/2010-October/590223.html – Pat

Verwandte Themen