2011-11-17 13 views
18

Estoy registrando eventos en mi código python usando el módulo de registro de Python. Tengo 2 archivos de registro que también deseo registrar, uno para contener la información del usuario y el otro un archivo de registro más detallado para los desarrolladores. Establecí los dos archivos de registro en los niveles que quiero (usr.log = INFO y dev.log = ERROR) pero no puedo resolver cómo restringir el registro al archivo usr.log para que solo se escriban los registros de nivel de INFO al archivo de registro en lugar de INFO más todo lo demás por encima, por ejemplo INFO, ADVERTENCIA, ERROR y CRÍTICO.nivel específico de registro de Python

Esto es básicamente mi código: -

import logging 

logger1 = logging.getLogger('') 
logger1.addHandler(logging.FileHandler('/home/tmp/usr.log') 
logger1.setLevel(logging.INFO) 
logger2 = logging.getLogger('') 
logger2.addHandler(logging.FileHandler('/home/tmp/dev.log') 
logger2.setLevel(logging.ERROR) 

logging.critical('this to be logged in dev.log only') 
logging.info('this to be logged to usr.log and dev.log') 
logging.warning('this to be logged to dev.log only') 

Cualquier ayuda sería grande gracias.

Respuesta

34

Estoy en general de acuerdo con David, pero creo que hay que decir más. Parafraseando The Princess Bride - No creo que este código signifique lo que piensas que significa. El código tiene:

logger1 = logging.getLogger('') 
... 
logger2 = logging.getLogger('') 

lo que significa que logger1 y logger2 son la misma registrador, por lo que cuando se establece el nivel de logger2 de error que en realidad terminan estableciendo el nivel de logger1 al mismo tiempo. Para obtener dos registradores diferentes, deberá proporcionar dos nombres de registrador diferentes. Por ejemplo:

logger1 = logging.getLogger('user') 
... 
logger2 = logging.getLogger('dev') 

Peor aún, a la que llama critical(), info() y warning() métodos del módulo de registro y esperar que tanto los registradores recibirán los mensajes. Esto solo funciona porque utilizó la cadena vacía como nombre para logger1 y logger2 y, por lo tanto, no solo son el mismo registrador, también son el registrador de raíz. Si utiliza diferentes nombres para los dos registradores como he sugerido, deberá llamar a los métodos critical(), info() y warning() en cada registrador de forma individual (es decir, necesitará dos llamadas en lugar de solo una).

Lo que creo que realmente quieres es tener dos handlers diferentes en un único registrador. Por ejemplo:

import logging 

mylogger = logging.getLogger('mylogger') 
handler1 = logging.FileHandler('usr.log') 
handler1.setLevel(logging.INFO) 
mylogger.addHandler(handler1) 
handler2 = logging.FileHandler('dev.log') 
handler2.setLevel(logging.ERROR) 
mylogger.addHandler(handler2) 
mylogger.setLevel(logging.INFO) 

mylogger.critical('A critical message') 
mylogger.info('An info message') 

Una vez que haya realizado este cambio, entonces se puede utilizar como filters David ya se ha mencionado.Aquí hay un filtro de muestra rápida:

class MyFilter(object): 
    def __init__(self, level): 
     self.__level = level 

    def filter(self, logRecord): 
     return logRecord.levelno <= self.__level 

se puede aplicar el filtro a cada uno de los dos manipuladores como este:

handler1.addFilter(MyFilter(logging.INFO)) 
... 
handler2.addFilter(MyFilter(logging.ERROR)) 

Esto restringirá cada manipulador sólo a escribir mensajes de registro en el nivel especificado.

+0

@srgerg Gracias por tomarse el tiempo para explicarlo, eso tiene mucho más sentido ahora. – user788462

+2

Para emitir el registro solo en el nivel especificado, ¿no sería necesario que la condición fuera 'logRecord.levelno == self .__ level' en lugar de' <= '? – samstav

+0

Oh, supongo que el otro filtro incorporado hará la comparación '> ='. – samstav

7

Primero: esto es algo bastante extraño de querer hacer, y me parece un ligero mal uso del sistema de registro. No puedo imaginar ninguna situación en la que tenga sentido notificar al usuario sobre el funcionamiento normal del programa, pero no sobre las cosas que son más importantes. Los niveles de registro se deben usar para indicar la importancia; si tiene mensajes que solo interesan a los desarrolladores, debe usar algún otro mecanismo para distinguirlos (como a qué registrador los envía).

Dicho esto, puede implementar el filtrado arbitrario de registros al crear una subclase Filter cuyo método filter implementa los criterios deseados e instalarlo en el controlador adecuado.

Cuestiones relacionadas