2011-07-27 12 views
9

¿Cuál es el método más simple para cambiar temporalmente el formato del mensaje de registro, en Python (a través del módulo de registro)?¿Cómo cambiar el formato de los mensajes registrados temporalmente en Python?

El objetivo es tener algún formato de mensaje estándar, mientras se puede agregar temporalmente información sobre algún archivo que se está leyendo (como su nombre); el formato del mensaje debe volver a su valor predeterminado cuando el archivo ya no se está leyendo. El programa que produce los mensajes es y no sabe qué archivo se está leyendo, por lo que sería bueno si su mensaje incluyera automáticamente el nombre del archivo relevante (el mensaje de error sería: "ERROR al leer el archivo ***: ... "en lugar de" ERROR: ... ").

+0

He actualizado mi respuesta. –

Respuesta

7

Aquí es una solución simple, que se puede deducir de Vinay Sajip 's propia HOWTO; Básicamente se actualiza el registro formateador con setFormatter():

import logging 

logger = logging.getLogger() # Logger 
logger_handler = logging.StreamHandler() # Handler for the logger 
logger.addHandler(logger_handler) 

# First, generic formatter: 
logger_handler.setFormatter(logging.Formatter('%(message)s')) 
logger.error('error message') # Test 

# New formatter for the handler: 
logger_handler.setFormatter(logging.Formatter('PROCESSING FILE xxx - %(message)s')) 
logger.error('error message') # Test 

Esto produce correctamente:

error message 
PROCESSING FILE xxx - error message 

(donde xxx se puede ajustar de forma dinámica en el fichero que está siendo procesado, tal como pidió en la pregunta).

+0

No estoy seguro de por qué esto se considera una solución. Los manejadores determinan el destino del registro, los formateadores determinan el formato de registro; estos dos pueden considerarse ortogonales. Si deseo cambiar temporalmente mi formato de registro para un registrador específico (por ejemplo, el logger 'paquete1.modulo2') para agregar alguna información contextual específica del módulo, me gustaría hacer esto para * todos * los manejadores del registrador. Enumerar todos los controladores que bien pueden ser utilizados por todos los demás registradores, cambiar el formato temporalmente y luego volver a cambiarlo para no romper los otros registradores no es una solución. – dtheodor

+0

De hecho, esto es lo que tendría que hacerse en esta situación más extrema, donde uno tiene poco control sobre cómo se distribuyen los manipuladores entre los registradores. Este es un caso específico y desafortunado.Ahora, hacer esto todavía se puede hacer de acuerdo con esta respuesta, por lo que me parece bien (descargo de responsabilidad: ambos hice la pregunta y proporcioné esta respuesta). Lo que sería interesante sería tener una pregunta específica para el esquema del caso en el comentario anterior, junto con la respuesta específica correspondiente; esto pertenece a otra entrada de StackOverflow. – EOL

6

Existen varias formas. Además del argumento already documented ones (extra para registrar llamadas, LoggerAdapter, Filter), otra forma sería especificar una clase de formato personalizada, cuya instancia puede mantener informada sobre el archivo que se está procesando. Por ejemplo:

class FileProcessingFormatter(logging.Formatter): 
    def __init__(self, fmt, datefmt=None, current_file=None): 
     super(FileProcessingFormatter, self).__init__(fmt, datefmt) 
     self.orig_fmt = fmt 
     self.current_file = current_file 

    def format(self, record): 
     if self.current_file is None: 
      self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__', '') 
     else: 
      self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__', 
          ' while processing %r' % self.current_file) 
     return super(FileProcessingFormatter, self).format(record) 

una instancia del formateador ...

f = FileProcessingFormatter('%(levelname)s__FILE_PLACEHOLDER__ %(message)s') 
for h in relevant_handlers: 
    h.setFormatter(f) 

Procesar archivos ...

f.current_file = fn 
process_file(fn) 
f.current_file = None 

Esto es muy simple - por ejemplo, no para su uso en entornos roscados si el procesamiento de archivos se realiza por diferentes hilos al mismo tiempo.

Actualización: Aunque los manipuladores del registrador de la raíz son accesibles a través de logging.getLogger().handlers, este es un detalle de implementación que podría cambiar. Como su requisito no es tan básico, quizás pueda usar dictConfig() para configurar su registro (disponible a través del proyecto logutils para versiones anteriores de Python).

+0

Gracias. ¿Se puede obtener 'relevant_handlers' para un manejador definido solo a través de' logging.basicConfig() '? si no, ¿cómo se puede definir 'relevant_handlers'? – EOL

+0

Gracias por la actualización. Necesito leer su HOWTO de registro, y tal vez más, antes de poder implementar cualquier solución concreta ... – EOL

Cuestiones relacionadas