timedrotatingfilehandler example python logging

timedrotatingfilehandler - python logging example



Logging, StreamHandler y streams estándar (3)

No puedo entender cómo registrar mensajes de nivel de información en stdout, sino todo lo demás en stderr. Ya leí este http://docs.python.org/library/logging.html . ¿Cualquier sugerencia?


Como mi edición fue rechazada, esta es mi respuesta. La respuesta de @ goncalopp es buena, pero no está sola ni funciona de la caja. Aquí está mi versión mejorada:

import sys, logging class LogFilter(logging.Filter): """Filters (lets through) all messages with level < LEVEL""" # http://.com/a/24956305/408556 def __init__(self, level): self.level = level def filter(self, record): # "<" instead of "<=": since logger.setLevel is inclusive, this should # be exclusive return record.levelno < self.level MIN_LEVEL = logging.DEBUG stdout_hdlr = logging.StreamHandler(sys.stdout) stderr_hdlr = logging.StreamHandler(sys.stderr) log_filter = LogFilter(logging.WARNING) stdout_hdlr.addFilter(log_filter) stdout_hdlr.setLevel(MIN_LEVEL) stderr_hdlr.setLevel(max(MIN_LEVEL, logging.WARNING)) # messages lower than WARNING go to stdout # messages >= WARNING (and >= STDOUT_LOG_LEVEL) go to stderr rootLogger = logging.getLogger() rootLogger.addHandler(stdout_hdlr) rootLogger.addHandler(stderr_hdlr) logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # Example Usage >>> logger.debug("A DEBUG message") >>> logger.info("An INFO message") >>> logger.warning("A WARNING message") >>> logger.error("An ERROR message") >>> logger.critical("A CRITICAL message")


En general, creo que tiene sentido redirigir los mensajes inferiores a WARNING a stdout , en lugar de solo mensajes INFO .

Basado en la excelente respuesta de Vinay Sajip , se me ocurrió esto:

class MaxLevelFilter(Filter): ''''''Filters (lets through) all messages with level < LEVEL'''''' def __init__(self, level): self.level = level def filter(self, record): return record.levelno < self.level # "<" instead of "<=": since logger.setLevel is inclusive, this should be exclusive MIN_LEVEL= DEBUG #... stdout_hdlr = StreamHandler(sys.stdout) stderr_hdlr = StreamHandler(sys.stderr) lower_than_warning= MaxLevelFilter(WARNING) stdout_hdlr.addFilter( lower_than_warning ) #messages lower than WARNING go to stdout stdout_hdlr.setLevel( MIN_LEVEL ) stderr_hdlr.setLevel( max(MIN_LEVEL, WARNING) ) #messages >= WARNING ( and >= STDOUT_LOG_LEVEL ) go to stderr #...


El siguiente script, log1.py :

import logging, sys class SingleLevelFilter(logging.Filter): def __init__(self, passlevel, reject): self.passlevel = passlevel self.reject = reject def filter(self, record): if self.reject: return (record.levelno != self.passlevel) else: return (record.levelno == self.passlevel) h1 = logging.StreamHandler(sys.stdout) f1 = SingleLevelFilter(logging.INFO, False) h1.addFilter(f1) rootLogger = logging.getLogger() rootLogger.addHandler(h1) h2 = logging.StreamHandler(sys.stderr) f2 = SingleLevelFilter(logging.INFO, True) h2.addFilter(f2) rootLogger.addHandler(h2) logger = logging.getLogger("my.logger") logger.setLevel(logging.DEBUG) logger.debug("A DEBUG message") logger.info("An INFO message") logger.warning("A WARNING message") logger.error("An ERROR message") logger.critical("A CRITICAL message")

cuando se ejecuta, produce los siguientes resultados.

C:/temp>log1.py A DEBUG message An INFO message A WARNING message An ERROR message A CRITICAL message

Como era de esperar, ya que en una terminal sys.stdout y sys.stderr son iguales. Ahora, vamos a redireccionar stdout a un archivo, tmp :

C:/temp>log1.py >tmp A DEBUG message A WARNING message An ERROR message A CRITICAL message

Por lo tanto, el mensaje INFO no se ha impreso en el terminal, pero los mensajes dirigidos a sys.stderr se han impreso. Veamos lo que hay en tmp :

C:/temp>type tmp An INFO message

Entonces ese enfoque parece hacer lo que quieras.