2010-02-20 8 views

risposta

1
Non

necessariamente una buona idea (che potrebbe essere fonte di confusione per vedere Informazioni ed eseguire il debug dei messaggi mescolati con uscita normale!), Ma fattibile, dal momento che è possibile avere più oggetti del gestore e di un personalizzato filter per ognuno di essi, al fine di scegliere e scegliere quale registro registra ogni gestore può gestire.

+1

per favore potresti mostrare (!) Come aggiungere un filtro adatto che fa il lavoro ? Il suggerimento di gcb qui sotto significa che "logger" continua a essere inviato a stderr, ma "ch" restituisce la stessa cosa allo stdout. Dato che ch dipende dal logger, come si può impostare un filtro sul logger senza di esso quindi applicando anche a ch? Confuso. –

6
+0

Vorrei solo eseguire il debug e il messaggio info in stdout e nessun messaggio di avviso o di errore . La documentazione – Dinoboff

+0

è aggiornata, il collegamento corretto è su http://docs.python.org/library/logging.handlers.html#module-logging.handlers – gcb

3

direttamente dai documenti aggiornati, copre abbastanza bene questo caso ora.

http://docs.python.org/howto/logging.html#logging-advanced-tutorial

import sys # Add this. 
import logging 

# create logger 
logger = logging.getLogger('simple_example') 
logger.setLevel(logging.DEBUG) 

# create console handler and set level to debug 
ch = logging.StreamHandler(sys.__stdout__) # Add this 
ch.setLevel(logging.DEBUG) 

# create formatter 
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 

# add formatter to ch 
ch.setFormatter(formatter) 

# add ch to logger 
logger.addHandler(ch) 

# 'application' code 
logger.debug('debug message') 
logger.info('info message') 
logger.warn('warn message') 
logger.error('error message') 
logger.critical('critical message') 

ho accennato sulle osservazioni dei due modifiche richieste dal esempio per rendere l'output andare a stdout. puoi anche utilizzare i filtri per reindirizzare a seconda del livello.

ulteriori informazioni per capire i cambiamenti è al http://docs.python.org/library/logging.handlers.html#module-logging.handlers

+5

Questo reindirizza solo allo stdout, ma non filtra a seconda del livello di stderr. – guettli

+0

@guettli "puoi anche utilizzare i filtri per reindirizzare a seconda del livello" – gcb

+2

@gcb per favore potresti mostrare (!) Come aggiungere un filtro adatto che fa il lavoro? Il tuo suggerimento significa che "logger" continua a essere inviato a stderr, ma "ch" restituisce la stessa cosa allo stdout. Dato che ch dipende dal logger, come si può impostare un filtro sul logger senza di esso quindi applicando anche a ch? Confuso. –

5

Ho avuto lo stesso problema e ho scritto un gestore di registrazione personalizzata denominata SplitStreamHandler:

import sys 
import logging 

class SplitStreamHandler(logging.Handler): 
    def __init__(self): 
     logging.Handler.__init__(self) 

    def emit(self, record): 
     # mostly copy-paste from logging.StreamHandler 
     try: 
      msg = self.format(record) 
      if record.levelno < logging.WARNING: 
       stream = sys.stdout 
      else: 
       stream = sys.stderr 
      fs = "%s\n" 

      try: 
       if (isinstance(msg, unicode) and 
        getattr(stream, 'encoding', None)): 
        ufs = fs.decode(stream.encoding) 
        try: 
         stream.write(ufs % msg) 
        except UnicodeEncodeError: 
         stream.write((ufs % msg).encode(stream.encoding)) 
       else: 
        stream.write(fs % msg) 
      except UnicodeError: 
       stream.write(fs % msg.encode("UTF-8")) 

      stream.flush() 
     except (KeyboardInterrupt, SystemExit): 
      raise 
     except: 
      self.handleError(record) 
+0

So che è leggermente fuori tema, ma qualcuno può spiegare la codifica/decodifica try/catch logic qui in termini di codifica dei caratteri? – Chris

19
import logging 
import sys 

class LessThanFilter(logging.Filter): 
    def __init__(self, exclusive_maximum, name=""): 
     super(LessThanFilter, self).__init__(name) 
     self.max_level = exclusive_maximum 

    def filter(self, record): 
     #non-zero return means we log this message 
     return 1 if record.levelno < self.max_level else 0 

#Get the root logger 
logger = logging.getLogger() 
#Have to set the root logger level, it defaults to logging.WARNING 
logger.setLevel(logging.NOTSET) 

logging_handler_out = logging.StreamHandler(sys.stdout) 
logging_handler_out.setLevel(logging.DEBUG) 
logging_handler_out.addFilter(LessThanFilter(logging.WARNING)) 
logger.addHandler(logging_handler_out) 

logging_handler_err = logging.StreamHandler(sys.stderr) 
logging_handler_err.setLevel(logging.WARNING) 
logger.addHandler(logging_handler_err) 

#demonstrate the logging levels 
logger.debug('DEBUG') 
logger.info('INFO') 
logger.warning('WARNING') 
logger.error('ERROR') 
logger.critical('CRITICAL') 

Attuazione a parte, io penso che sia una buona idea usare le funzionalità di registrazione in python per l'output sul terminale, in particolare perché è possibile aggiungere un altro gestore per accedere anche a un file. Se imposti lo stdout come INFO invece di DEBUG, puoi anche includere ulteriori informazioni DEBUG che l'utente non vedrebbe nel file di registro in modo standard.

+0

Da dove viene la classe 'LessThanFilter'. Impossibile trovarlo nelle librerie Python3. – buhtz

+2

L'ho scritto (e fornito l'implementazione), non è nelle librerie standard. –

+0

Grazie mille. Questo è il primo posto in cui ho trovato qualcuno che menziona il livello di registrazione predefinito di Warning. Ho perso un giorno per questo. Viene ripristinata una parvenza di santiy. GRAZIE! – penderi

-1
#!/usr/bin/env python3 
# -*- coding: utf-8 -*- 
import logging 
import sys 

class LessThenFilter(logging.Filter): 
    def __init__(self, level): 
     self._level = level 
     logging.Filter.__init__(self) 

    def filter(self, rec): 
     return rec.levelno < self._level 

log = logging.getLogger() 
log.setLevel(logging.NOTSET) 

sh_out = logging.StreamHandler(stream=sys.stdout) 
sh_out.setLevel(logging.DEBUG) 
sh_out.setFormatter(logging.Formatter('%(levelname)s: %(message)s')) 
sh_out.addFilter(LessThenFilter(logging.WARNING)) 
log.addHandler(sh_out) 

sh_err = logging.StreamHandler(stream=sys.stderr) 
sh_err.setLevel(logging.WARNING) 
sh_err.setFormatter(logging.Formatter('%(levelname)s: %(message)s')) 
log.addHandler(sh_err) 

logging.critical('x') 
logging.error('x') 
logging.warning('x') 
logging.info('x') 
logging.debug('x') 
Problemi correlati