Me doy cuenta de que el módulo de registro se comporta de manera graciosa. Me estoy perdiendo de algo ?Extraño: el registrador solo usa el formateador del primer controlador para las excepciones
Estoy haciendo lo habitual de tener dos controladores: un StreamHandler para registrar solo INFO y superior a la consola, y un FileHandler que también manejará toda la información de DEPURACIÓN.
Funcionó bien hasta que decidí tener un formato diferente para las excepciones. Quería un stacktrace completo en el archivo, pero solo el tipo de excepción y el valor en la consola. Dado que los manejadores tienen una función setFormatter, y dado que parece fácil escribir una subclase de registro. Por lo demás, pensé que funcionaría.
El controlador de la consola y el manejador de archivos tienen su propio formateador. Las instrucciones de impresión en el código lo demuestran. Sin embargo, la llamada a logger.exception solo usará el formato Excepción del primer controlador agregado => la excepción se registra en el archivo con el formato que debería tener en la consola. Cambia el orden de las líneas de logger.addHandler y luego está el formatException del controlador de archivos que se usa en todas partes.
import logging
import sys
class ConsoleFormatter(logging.Formatter):
def formatException(self, exc_info):
# Ugly but obvious way to see who's talking.
return "CONSOLE EXCEPTION %s: %s" % exc_info[:2]
def setup(path):
logger = logging.getLogger()
#
file_handler = logging.FileHandler(path, mode='w')
if __debug__:
file_handler.setLevel(logging.DEBUG)
else:
file_handler.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s %(levelname)-8s "
"%(name)-16s %(message)s "
"[%(filename)[email protected]%(lineno)d in %(funcName)s]")
file_handler.setFormatter(formatter)
#
console_handler = logging.StreamHandler(sys.stderr)
console_handler.setLevel(logging.INFO)
console_formatter = ConsoleFormatter("%(levelname)-8s - %(message)s")
console_handler.setFormatter(console_formatter)
# >>> FUN HAPPENS HERE <<<
# Only the formatter of the first handler is used ! Both on the console
# and in the file. Change the order of these two lines to see.
logger.addHandler(console_handler)
logger.addHandler(file_handler)
#
# Proof that the two handlers have different formatters:
print logger.handlers
print file_handler.formatter.formatException
print console_formatter.formatException
#
logger.setLevel(logging.DEBUG)
logger.info("Logger ready.")
setup('test.log')
logger = logging.getLogger()
logger.debug("Only visible in the file.")
try:
1/0
except ZeroDivisionError:
logger.exception("boom")
¿Qué está pasando?
EDITAR: Estoy usando python 2.6 por cierto. EDITAR: Typo en el código sobre el nombre de la variable "console_formatter" corregido.
¡Excelente! Al subclasar el registro. Por supuesto, pude anular el formato(). Este método reemplazado establece record.exc_text en None antes de llamar al formato de superclase() y lo restaura a su valor anterior justo después. De esa forma, deshabilito el almacenamiento en caché del texto de excepción sin duplicar ningún código. Luego, uso este CachelessFormatter como una clase base para mis dos controladores y funciona \ o /. Gracias ! – Niriel