python - values - ¿Cómo se pueden enviar mensajes de registro INFO y DEPURAR a stdout y un mensaje de nivel superior a stderr?
python logging multiple files (6)
¿Hay alguna manera fácil con el módulo de registro de Python para enviar mensajes con un nivel DEBUG o INFO y el que tiene un nivel más alto a diferentes flujos?
¿Es una buena idea de todos modos?
No es necesariamente una buena idea (¡puede ser confuso ver información y depurar mensajes mezclados con salida normal!), Pero es factible, ya que puede tener múltiples objetos de manejador y un filtro personalizado para cada uno de ellos, para seleccionar y elegir registros de registro que maneja cada controlador.
Sí. Debe definir múltiples controladores para su registro.
http://docs.python.org/library/logging.html#logging-to-multiple-destinations
http://docs.python.org/library/logging.handlers.html#module-logging.handlers
directamente desde los documentos actualizados, cubre este caso bastante bien ahora.
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'')
He mencionado en los comentarios los dos cambios requeridos en el ejemplo para hacer que la salida vaya a stdout. también puede usar filtros para redirigir dependiendo del nivel.
Para obtener más información sobre cómo entender los cambios, visite http://docs.python.org/library/logging.handlers.html#module-logging.handlers.
Tuve el mismo problema y escribí un controlador de registro personalizado llamado 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)
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'')
Dejando a un lado la implementación, creo que es una buena idea utilizar las funciones de registro en python para enviarlas a la terminal, en particular porque puede agregar otro controlador para iniciar sesión en un archivo. Si establece que stdout sea INFO en lugar de DEPURAR, incluso puede incluir información de DEPURACIÓN adicional que el usuario no vería normalmente en el archivo de registro.
#!/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'')