Python logging – ¿Hay algo debajo de DEBUG?

En algunas otras tecnologías, ocasionalmente usamos un nivel de registro por debajo de DEBUG que creo que se llamó “detallado”. Me doy cuenta de que la necesidad de tal nivel es muy subjetiva. Pero en mi mente, “solo” tener INFO y DEBUG no es suficiente. Tuvimos momentos en los que se necesitaba registrar algo muy spam (más spam que depuración). En la práctica, generaríamos comstackciones sin que estuviera activado, pero en algunas ocasiones habilitaríamos este nivel de registro después de que todo el producto estuviera instalado en alguna configuración de control de calidad, mientras rastreamos un error, etc.

¿Hay alguna manera (fácil o no) de registrar algo por debajo del nivel DEBUG utilizando la biblioteca de registro de python estándar?

En un archivo temp.py puedo hacer lo siguiente:

logging.addLevelName(5,"verbose") VERBOSE = 5 logger = logging.getLogger("foo") logger.setLevel(VERBOSE) logger.log(VERBOSE,"blah!") 

Esto funciona cuando ejecuto temp.py dentro de mi IDE (y de los registros a la salida estándar) pero nuestros demonios reales usan la syntax de configuración estándar de archivos / diccionarios para configurar el registro y no veo ninguna forma de indicar que se debe usar el nivel 5 para demonio.

¿Estoy persiguiendo algo que no es realmente factible?

Para aquellos que podrían preguntarse por qué necesitaría algo más bajo que DEBUG, es por el tipo ocasional de registro que puede ocurrir con mucha frecuencia (tal vez un bucle interno) que normalmente no querría ver incluso en DEBUG pero en algún sistema de producción podría ser útil habilitarlo de vez en cuando sin necesidad de agregar más registro al código fuente y volver a implementarlo, etc.

EDIT1 – Claramente, la biblioteca de registro permite niveles personalizados. Dado que DEBUG es el nivel 10, hay espacio en algún lugar en el rango de 1..9. Si defino un nivel personalizado (como en el código de ejemplo anterior), supongo que mi pregunta real es ¿cómo habilito ese nivel de registro desde el archivo de configuración de registro de json?

EDIT2 – Lo siguiente funcionaría si no fuera por el hecho de que necesitamos / usamos archivos de configuración json (un requisito que no puedo cambiar):

 import logging logging.basicConfig(filename='example.log',level=5) VERBOSE = 5 logging.addLevelName(5,"verbose") logger = logging.getLogger("bar") logger.log(VERBOSE,"blah!") 

EDIT3 – Lo descubrí … La llamada a

 logging.addLevelName(5,"VERBOSE") 

es critico. Simplemente no lo tenía en el lugar correcto. En mi caso, solo necesitaba hacer que la llamada anterior se realice antes de la llamada a las bibliotecas de registro dictConfig (…). Después de hacer esto, fui capaz de ingresar a nuestro archivo de configuración de registro y desmontar las cosas (tanto en el controlador de archivos como en la raíz) a VERBOSE y funcionó.

Por supuesto, la statement de registro en sí no es exactamente elegante porque llamas:

 self.logger.log(VERBOSE,"Something very spammy") 

más bien que

 self.logger.verbose("Something very spammy") 

Pero realmente no quería modificar ningún código de la biblioteca del registrador (he estado allí, hecho eso, tengo la camiseta).

¡Gracias a todos!

Y para aquellos que piensan que no se necesita nada más bajo que DEBUG, más poder para usted 🙂

DEBUG es el nivel más bajo entre los proporcionados por el módulo de registro: ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL') . Sus valores numéricos están aquí: http://docs.python.org/howto/logging.html#logging-levels

Puede crear niveles personalizados (aunque los documentos dicen que eso rara vez debería ser necesario e incluso puede ser indeseable). Si quieres agregar un nivel, la técnica es simple:

 >>> logging.addLevelName(5, "VERBOSE") 

Aunque puede agregar un nivel personalizado, puede ser un mejor enfoque agregar algunos filtros que brinden un nivel de control más preciso.

Incluso puede ir más allá y agregar un método logger.verbose, aunque le sugiero encarecidamente que no lo haga por varios motivos (bastante cubierto en el cómo hacer el registro ). De todos modos, si decides que realmente quieres tener uno, aquí está el código:

 logging.VERBOSE = 5 logging.addLevelName(logging.VERBOSE, "VERBOSE") logging.Logger.verbose = lambda inst, msg, *args, **kwargs: inst.log(logging.VERBOSE, msg, *args, **kwargs) 

La respuesta de @voitek funciona muy bien, pero se olvidó de logging.verbose parche logging.verbose .

 logging.VERBOSE = 5 logging.addLevelName(logging.VERBOSE, "VERBOSE") logging.Logger.verbose = lambda inst, msg, *args, **kwargs: inst.log(logging.VERBOSE, msg, *args, **kwargs) logging.verbose = lambda msg, *args, **kwargs: logging.log(logging.VERBOSE, msg, *args, **kwargs) 

Esto ahora también funcionará con;

 logging.verbose(*args, **kwargs) 

Agregando a la respuesta de @ sleepycal, es posible que también desee agregar un método detallado al LoggerAdapter:

 logging.VERBOSE = 5 logging.addLevelName(logging.VERBOSE, "VERBOSE") logging.Logger.verbose = lambda inst, msg, *args, **kwargs: inst.log(logging.VERBOSE, msg, *args, **kwargs) logging.LoggerAdapter.verbose = lambda inst, msg, *args, **kwargs: inst.log(logging.VERBOSE, msg, *args, **kwargs) logging.verbose = lambda msg, *args, **kwargs: logging.log(logging.VERBOSE, msg, *args, **kwargs)