stringvar - Hacer que los registradores de Python envíen todos los mensajes a la salida estándar además del archivo de registro
stringvar python 3 (6)
¿Hay alguna manera de hacer que el registro de Python utilizando el módulo de logging
genere automáticamente las cosas a la salida estándar además del archivo de registro donde se supone que deben ir? Por ejemplo, me gustaría que todas las llamadas a logger.warning
, logger.critical
, logger.error
vayan a sus lugares previstos pero, además, siempre se copien en la logger.critical
logger.error
. Esto es para evitar la duplicación de mensajes como:
mylogger.critical("something failed")
print "something failed"
Aquí hay una solución basada en la función de configuración dictConfig
. En lugar de enviar todos los mensajes de registro a la salida estándar, envía mensajes con un nivel de registro ERROR y superior a stderr y todo lo demás a la salida estándar. Esto puede ser útil si otras partes del sistema están escuchando stderr / stdout.
import logging
import logging.config
import sys
class _ExcludeErrorsFilter(logging.Filter):
def filter(self, record):
"""Filters out log messages with log level ERROR (numeric value: 40) or higher."""
return record.levelno < 40
config = {
''version'': 1,
''filters'': {
''exclude_errors'': {
''()'': _ExcludeErrorsFilter
}
},
''formatters'': {
''my_formatter'': {
''format'': ''(%(process)d) %(asctime)s %(name)s (line %(lineno)s) | %(levelname)s %(message)s''
}
},
''handlers'': {
''console_stderr'': {
# Directs log messages with log level ERROR or higher to stderr
''class'': ''logging.StreamHandler'',
''level'': ''ERROR'',
''formatter'': ''my_formatter'',
''stream'': sys.stderr
},
''console_stdout'': {
# Directs log messages with log level lower than ERROR to stdout
''class'': ''logging.StreamHandler'',
''level'': ''DEBUG'',
''formatter'': ''my_formatter'',
''filters'': [''exclude_errors''],
''stream'': sys.stdout
},
''file'': {
# Directs all log messages to a file
''class'': ''logging.FileHandler'',
''level'': ''DEBUG'',
''formatter'': ''my_formatter'',
''filename'': ''my.log'',
''encoding'': ''utf8''
}
},
''root'': {
''level'': ''NOTSET'',
''handlers'': [''console_stderr'', ''console_stdout'', ''file'']
},
}
logging.config.dictConfig(config)
Es posible usar múltiples manejadores.
import logging
import auxiliary_module
# create logger with ''spam_application''
log = logging.getLogger(''spam_application'')
log.setLevel(logging.DEBUG)
# create formatter and add it to the handlers
formatter = logging.Formatter(''%(asctime)s - %(name)s - %(levelname)s - %(message)s'')
# create file handler which logs even debug messages
fh = logging.FileHandler(''spam.log'')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
log.addHandler(fh)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
ch.setFormatter(formatter)
log.addHandler(ch)
log.info(''creating an instance of auxiliary_module.Auxiliary'')
a = auxiliary_module.Auxiliary()
log.info(''created an instance of auxiliary_module.Auxiliary'')
log.info(''calling auxiliary_module.Auxiliary.do_something'')
a.do_something()
log.info(''finished auxiliary_module.Auxiliary.do_something'')
log.info(''calling auxiliary_module.some_function()'')
auxiliary_module.some_function()
log.info(''done with auxiliary_module.some_function()'')
# remember to close the handlers
for handler in log.handlers:
handler.close()
log.removeFilter(handler)
Consulte: https://docs.python.org/2/howto/logging-cookbook.html
La forma más sencilla de iniciar sesión en un archivo y en stderr:
import logging
logging.basicConfig(filename="logfile.txt")
stderrLogger=logging.StreamHandler()
stderrLogger.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
logging.getLogger().addHandler(stderrLogger)
La forma más sencilla:
import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
Puede crear dos controladores para el archivo y la basicConfig
y luego crear un registrador con el argumento de los handlers
para basicConfig
. Podría ser útil si tiene el mismo log_level y formato de salida para ambos controladores:
import logging
import sys
file_handler = logging.FileHandler(filename=''tmp.log'')
stdout_handler = logging.StreamHandler(sys.stdout)
handlers = [file_handler, stdout_handler]
logging.basicConfig(
level=logging.DEBUG,
format=''[%(asctime)s] {%(filename)s:%(lineno)d} %(levelname)s - %(message)s'',
handlers=handlers
)
logger = logging.getLogger(''LOGGER_NAME'')
Toda la salida de registro es manejada por los manejadores; simplemente agregue un logging.StreamHandler()
al registrador raíz.
Este es un ejemplo de configuración de un controlador de flujo (usando stdout
lugar del stderr
predeterminado) y agregarlo al registrador raíz:
import logging
import sys
root = logging.getLogger()
root.setLevel(logging.DEBUG)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter(''%(asctime)s - %(name)s - %(levelname)s - %(message)s'')
handler.setFormatter(formatter)
root.addHandler(handler)