Python3 agregar nivel de registro

Tengo este código que funciona bien para mí.

import logging import logging.handlers logger = None def create_logger(): global logger logger = logging.getLogger('Logger') logger.setLevel(logging.DEBUG) handler = logging.handlers.RotatingFileHandler("C:/Users/user/Desktop/info.log", maxBytes=1000000, backupCount=20) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) create_logger() logger.info("Text info") logger.debug("Text debug") logger.warning("Text warning") logger.error("Text error") logger.critical("Text critical") 

Y la salida se ve muy bien:

2017-12-19 15: 06: 43,021 – Registrador – INFO – Información de texto
2017-12-19 15: 06: 43,021 – Registrador – DEBUG – Depuración de texto
2017-12-19 15: 06: 43,022 – Registrador – ADVERTENCIA – Advertencia de texto
2017-12-19 15: 06: 43,022 – Registrador – ERROR – Error de texto
2017-12-19 15: 06: 43,022 – Registrador – CRÍTICO – Texto crítico

Bueno, quiero agregar un nuevo nivel de registro como este:

 logger.message("Text message") 

Y la salida debería ser así.

2017-12-19 15: 06: 43,022 – Registrador – MENSAJE – Mensaje de texto

Gracias

De la documentación de registro (énfasis añadido):

Definir sus propios niveles es posible, pero no debería ser necesario , ya que los niveles existentes se han elegido sobre la base de la experiencia práctica. Sin embargo, si está convencido de que necesita niveles personalizados, debe tener mucho cuidado al hacer esto, y posiblemente sea una muy mala idea definir niveles personalizados si está desarrollando una biblioteca . Esto se debe a que si varios autores de bibliotecas definen sus propios niveles personalizados, existe la posibilidad de que el registro de salida de dichas bibliotecas múltiples utilizadas juntas sea difícil de controlar y / o interpretar por parte del desarrollador que usa, porque un valor numérico dado puede significar cosas diferentes Para diferentes bibliotecas.

Una visión general de los niveles de registro predeterminados:

vista general del nivel loggin

Pero si aún así lo desea, puede crear su propio nivel de registro:

En el módulo de logging , _levelToName y _nameToLevel son asignaciones entre los nombres y niveles de registro. En lugar de agregarlos manualmente, la función addLevelName() hace esto por usted.

Aquí, se agrega un nuevo nivel de registro llamado MESSAGE con el nivel de registro 25 :

 import logging # Define MESSAGE log level MESSAGE = 25 # "Register" new loggin level logging.addLevelName(MESSAGE, 'MESSAGE') # addLevelName(25, 'MESSAGE') # Verify assert logging.getLevelName(MESSAGE) == 'MESSAGE' 

Si no desea crear su propia clase de registrador pero aún desea registrar otros niveles de registro, puede usar el Logger.log(level, msg) en los registradores tradicionales:

 logging.log(MESSAGE, 'This is a message') 

EDITAR: Añadir mensaje directamente

  def message(self, msg, *args, **kwargs): if self.isEnabledFor(MESSAGE): self._log(MESSAGE, msg, args, **kwargs) 

Haga que el message() funcione en el logging :

  logging.message = message # or setattr(logging, 'message', message) 

Haga que el message() funcione en el registrador:

  logging.Logger.message = message # or setattr(logging.Logger, 'message', message) 

Hacer clase personalizada Logger

Puede crear su propia clase de registrador para hacer un método de message(msg) , que se usará de manera similar a los demás (por ejemplo, info(msg) , warning(msg) , etc.)

En el siguiente ejemplo, se crea un nuevo registrador con un método de message(msg) para registrar MENSAJE :

 class MyLogger(logging.Logger): def message(self, msg, *args, **kwargs): if self.isEnabledFor(MESSAGE): self._log(MESSAGE, msg, args, **kwargs) 

Obtener registrador

No estoy seguro de cuál es la mejor manera de hacer que funcione con logging.getLogger(name) , pero a continuación hay dos enfoques. Árbitro. Comentarios, creo que el primer enfoque es mejor:

O bien, haga que el nuevo registrador sea la clase de registro predeterminada, lo que significa que las nuevas instancias del registrador serán de la clase MyLogger lugar de la clase de logging.Logger predeterminado:

 logging.setLoggerClass(MyLogger) logger = logging.getLogger('A new logger name') logger.message('This seems to work') assert isInstance(logger, MyLogger) 

O simplemente loggerDict una instancia del registrador y agréguela al loggerDict en la instancia de logging.Manager activo. logging.Manager ( EDIT : no se recomienda, vea los comentarios):

 my_logger = MyLogger('Foo') logging.Logger.manager.loggerDict['Foo'] = my_logger logger = logging.getLogger('Foo') logger.message('This is the same instance as my_logger') assert logger is my_logger 

Utilice el nuevo nivel de registro

 # Use the new logger class logger.warning('Custom log levels might be a bad idea') logger.message('Here is a message') # Log with custom log level: logger.log(MESSAGE, 'This is a message') 

Esto supone que MESSAGE está predefinido como un valor numérico entero que representa el nivel de registro. (Por ejemplo, 25 como se mencionó anteriormente)