2012-01-12 16 views
5

Quiero hacer algo que pensé que era simple.Diferentes niveles de registro en python

realidad con el módulo de registro de Python, estoy interesado tala todo en la línea de comandos a nivel determinado a partir de los argumentos de línea de comandos y registro en un archivo a un nivel de depuración fijo.

Creación de dos registradores diferentes con diferentes niveles no funciona, pero establecer los niveles de dos manipuladores diferentes tanto añaden al registrador de la raíz no funciona bien, por lo que cualquier idea acerca de cómo en realidad debería hacerlo? (lectura en otros enlaces del segundo enfoque debería funcionar, por lo que estoy haciendo algo más estúpida?)

Este es el código que establece mi sistema de registro en el momento:

class LoggerSetup(object): 
    """Setup the different logger objects 
    """ 

    def __init__(self): 
     self.root_logger = logging.getLogger() 
     self.shell_hdlr = logging.StreamHandler() 

    #TODO: add another logging handler which stores to a temporary file 
    #which should be cleaned up later 
    def setup_shell_logger(self, log_level): 
     self.root_logger.setLevel(LOG_LEVELS[log_level]) 
     # in this way the root logger is not set but the handlers are set 
     self.shell_hdlr = logging.StreamHandler() 
     self.shell_hdlr.setLevel(LOG_LEVELS[log_level]) 
     self.shell_hdlr.setFormatter(StarFormatter()) 
     #FIXME: add the support for regular expression exclusion too 
     self.root_logger.addHandler(self.shell_hdlr) 

    def setup_log_include(self, log_include): 
     """Set up the filter to include log messages 
     """ 
     if log_include: 
      incl = FilterInclude(log_include) 
      self.shell_hdlr.addFilter(incl) 

    def setup_log_exclude(self, log_exclude): 
     """Set up the filters to exclude log messages 
     """ 
     if log_exclude: 
      excl = FilterExclude(log_exclude) 
      self.shell_hdlr.addFilter(excl) 

    def setup_file_logging(self): 
     """Set up the file logger, which always logs in DEBUG mode 
     even if the top level logger is set to another level 
     """ 
     #XXX: not working, one possible way to make it work is to create 
     #only one log, and different handler/filters to make to handle all 
     #the different outputs 
     file_handler = logging.FileHandler(LOG_FILENAME) 
     # the file logging is always in debug mode 
     file_handler.setLevel(logging.DEBUG) 
     formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s - %(asctime)s') 
     file_handler.setFormatter(formatter) 
     self.root_logger.addHandler(file_handler) 
+0

", pero establecer los niveles de dos manejadores diferentes ambos agregados al registrador de raíz no funciona "? ¿Puedes aclarar, por favor? –

Respuesta

12

Esto es algo que estoy usando todas mis aplicaciones de línea de comandos de Python. Es un poco más detallado, pero debe ser capaz de obtener un registrador que acepta un argumento opcional para crear un registrador de la consola en cualquier nivel, con independencia de lo que se registra en el archivo:

#!/usr/bin/env python 
import logging 
from argparse import ArgumentParser 

COMPANY_LOGGER = 'COMPANY.Python.Logger' 
CONSL_LEVEL_RANGE = range(0, 51) 
LOG_FILE = 'company.log' 
FORMAT_STR = '%(asctime)s %(levelname)s %(message)s' 

parser = ArgumentParser() 
parser.add_argument('-c', '--console-log', metavar='ARG', 
        type=int, choices=range(0, 51), 
        action='store', dest='console_log', 
        default=None, 
        help='Adds a console logger for the level specified in the range 1..50') 

args = parser.parse_args() 

# Create logger 
logger = logging.getLogger(COMPANY_LOGGER) 
logger.setLevel(logging.DEBUG) 
formatter = logging.Formatter(FORMAT_STR) 

# Add FileHandler and only log WARNING and higher 
fh = logging.FileHandler(LOG_FILE) 
fh.name = 'File Logger' 
fh.level = logging.WARNING 
fh.formatter = formatter 
logger.addHandler(fh) 

# Add optional ConsoleHandler 
if args.console_log: 
    ch = logging.StreamHandler() 
    ch.name = 'Console Logger' 
    ch.level = args.console_log 
    ch.formatter = formatter 
    logger.addHandler(ch) 

logger.debug('DEBUG') 
logger.info('INFO') 
logger.warning('WARNING') 
logger.critical('CRITICAL') 

Whenrun desde la línea de comandos que puede ver las diferencias en los niveles registrados.

-c1 equivale a "depurar y superior" (el más detallado), pero company.log es todavía sólo el registro ADVERTENCIA y superior:

~ zacharyyoung$ ./so.py -c1 
2012-01-12 08:59:50,086 DEBUG DEBUG 
2012-01-12 08:59:50,086 INFO INFO 
2012-01-12 08:59:50,087 WARNING WARNING 
2012-01-12 08:59:50,087 CRITICAL CRITICAL 

~ zacharyyoung$ cat company.log 
2012-01-12 08:59:50,087 WARNING WARNING 
2012-01-12 08:59:50,087 CRITICAL CRITICAL 

-c20 equivale a INFO:

~ zacharyyoung$ ./so.py -c20 
2012-01-12 09:00:09,393 INFO INFO 
2012-01-12 09:00:09,393 WARNING WARNING 
2012-01-12 09:00:09,393 CRITICAL CRITICAL 

~ zacharyyoung$ cat company.log 
2012-01-12 08:59:50,087 WARNING WARNING 
2012-01-12 08:59:50,087 CRITICAL CRITICAL 
2012-01-12 09:00:09,393 WARNING WARNING 
2012-01-12 09:00:09,393 CRITICAL CRITICAL 
+0

+1 Solo una sugerencia: creo que puedes evitar definir la función 'getConsoleLevel' si usas las palabras clave' type = int' y 'choices = xrange (51)' del método 'parser.add_argument'. Consulte el [final de esta sección en el documento] (https://docs.python.org/2/library/argparse.html#type). Y puede establecer un valor predeterminado de '21' y obtener el mismo nivel predeterminado que el módulo' logging'. – logc

+0

@logc: gracias por la sugerencia ... No estoy seguro de por qué no hice esto anteriormente (tal vez estaba preocupado por la forma en que se imprimió la declaración de ayuda), pero puedo ver que funciona igual de bien utilizando solo incorporados. Gracias :) –

Cuestiones relacionadas