Módulo Logging en Python

Si alguna vez has puesto una sentencia print() en tu código para mostrar el valor de alguna variable mientras tu programa se está ejecutando, has utilizado una forma de logging (registro) para depurar tu código. El registro es una gran manera de entender lo que está sucediendo en tu programa y en qué orden está sucediendo. El módulo de logging de Python facilita la creación de un registro de mensajes personalizados que escribes. Estos mensajes de registro describirán cuándo la ejecución del programa ha alcanzado la llamada a la función de registro y enumerarán cualquier variable que hayas especificado en ese momento. Por otro lado, un mensaje de registro perdido indica que una parte del código se ha saltado y nunca se ha ejecutado.

Para permitir que el módulo de logging muestre mensajes de registro en su pantalla mientras se ejecuta su programa, copie lo siguiente en la parte superior de su programa:

import logging
logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s -  %(levelname)
s -  %(message)s')

No necesita preocuparse demasiado por cómo funciona esto, pero básicamente, cuando Python registra un evento, crea un objeto LogRecord que contiene información sobre ese evento. La función basicConfig() del módulo de registro le permite especificar qué detalles sobre el objeto LogRecord desea ver y cómo desea que se muestren esos detalles.

Digamos que escribiste una función para calcular el factorial de un número. En matemáticas, el factorial 4 es 1 × 2 × 3 × 4, o 24. El factorial 7 es 1 × 2 × 3 × 4 × 5 × 6 × 7, o 5040. Abra una nueva pestaña del editor de archivos e ingrese el siguiente código. Tiene un error, pero también ingresará varios mensajes de registro para ayudarse a descubrir qué está fallando. Guarde el programa como factorialLog.py.

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s -  %(levelname)s -  %(message)s')
logging.debug('Start of program')

def factorial(n):
    logging.debug('Start of factorial(%s%%)'  % (n))
    total = 1
    for i in range(n + 1):
        total *= i
        logging.debug('i is ' + str(i) + ', total is ' + str(total))
    logging.debug('End of factorial(%s%%)'  % (n))
    return total

print(factorial(5))
logging.debug('End of program')

Aquí, usamos la función logging.debug() cuando queremos imprimir información de registro. Esta función debug() llamará a basicConfig() y se imprimirá una línea de información. Esta información tendrá el formato que especificamos en basicConfig() e incluirá los mensajes que pasamos a debug(). La llamada print(factorial(5)) es parte del programa original, por lo que el resultado se muestra incluso si los mensajes de registro están deshabilitados.

La salida de este programa se ve así:

2022-05-23 08:51:23,274 -  DEBUG -  Start of program
2022-05-23 08:51:23,274 -  DEBUG -  Start of factorial(5%)
2022-05-23 08:51:23,274 -  DEBUG -  i is 0, total is 0
2022-05-23 08:51:23,274 -  DEBUG -  i is 1, total is 0
2022-05-23 08:51:23,274 -  DEBUG -  i is 2, total is 0
2022-05-23 08:51:23,274 -  DEBUG -  i is 3, total is 0
2022-05-23 08:51:23,274 -  DEBUG -  i is 4, total is 0
2022-05-23 08:51:23,274 -  DEBUG -  i is 5, total is 0
2022-05-23 08:51:23,274 -  DEBUG -  End of factorial(5%)
0
2022-05-23 08:51:23,275 -  DEBUG -  End of program

La función factorial() devuelve 0 como el factorial de 5, lo cual no es correcto. El bucle for debe multiplicar el valor total por los números del 1 al 5 . Pero los mensajes de registro que muestra logging.debug() muestran que la variable i comienza en 0 en lugar de 1. Dado que cero multiplicado por cualquier cosa es cero, el resto de las iteraciones también tienen un valor incorrecto para el total. Los mensajes de registro proporcionan un rastro de migas de pan que pueden ayudarlo a descubrir cuándo las cosas comenzaron a salir mal.

Cambie la línea for i in range(n + 1): a for i in range( 1, n + 1):, y vuelva a ejecutar el programa. La salida se verá así:

2022-05-23 09:00:05,671 -  DEBUG -  Start of program
2022-05-23 09:00:05,671 -  DEBUG -  Start of factorial(5%)
2022-05-23 09:00:05,671 -  DEBUG -  i is 1, total is 1
2022-05-23 09:00:05,671 -  DEBUG -  i is 2, total is 2
2022-05-23 09:00:05,671 -  DEBUG -  i is 3, total is 6
2022-05-23 09:00:05,671 -  DEBUG -  i is 4, total is 24
2022-05-23 09:00:05,671 -  DEBUG -  i is 5, total is 120
2022-05-23 09:00:05,671 -  DEBUG -  End of factorial(5%)
120
2022-05-23 09:00:05,671 -  DEBUG -  End of program

La llamada factorial(5) devuelve correctamente 120 . Los mensajes de registro mostraban lo que estaba pasando dentro del bucle, lo que condujo directamente al error.

Puede ver que las llamadas a logging.debug() imprimieron no solo las cadenas que se les pasaron, sino también una marca de tiempo y la palabra DEBUG .

Escribir import logging y logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') es un poco difícil de manejar. Es posible que desee utilizar llamadas a print() en su lugar, pero no caiga en esta tentación. Una vez que hayas terminado de depurar, terminarás gastando mucho tiempo eliminando las llamadas a print() de tu código para cada mensaje de registro. Puede que incluso elimine accidentalmente algunas llamadas a print() que se estaban utilizando para mensajes que no eran de registro. Lo bueno de los mensajes de registro es que eres libre de llenar tu programa con tantos como quieras, y siempre puedes desactivarlos más tarde añadiendo una única llamada a logging.disable(logging.CRITICAL). A diferencia de print(), el módulo logging facilita el cambio entre mostrar y ocultar los mensajes de registro.

Los mensajes de registro están destinados al programador, no al usuario. Al usuario no le importará el contenido de algún valor del diccionario que necesite ver para ayudar a la depuración; utilice un mensaje de registro para algo así. Para los mensajes que el usuario querrá ver, como Archivo no encontrado o Entrada inválida, por favor introduzca un número, debería utilizar una llamada a print(). No querrá privar al usuario de información útil después de haber desactivado los mensajes de registro.

Los niveles de registro (logging levels) proporcionan una forma de categorizar sus mensajes de registro por importancia. Hay cinco niveles de registro, descritos en la Tabla 11-1 de menor a mayor importancia. Los mensajes se pueden registrar en cada nivel utilizando una función de registro diferente.

NivelFunción de registroDescripción
DEBUGlogging.debug()El nivel más bajo. Se utiliza para pequeños detalles. Por lo general, solo le importan estos mensajes cuando diagnostica problemas.
INFOlogging.info()Se utiliza para registrar información sobre eventos generales en su programa o confirmar que las cosas funcionan en su punto del programa.
WARNINGlogging.warning()Se utiliza para indicar un problema potencial que no impide que el programa funcione, pero que podría hacerlo en el futuro.
ERRORlogging.error()Se utiliza para registrar un error que hizo que el programa no pudiera hacer algo.
CRITICALlogging.critical()El nivel más alto. Se utiliza para indicar un error fatal que ha provocado o está a punto de provocar que el programa deje de ejecutarse por completo.

Su mensaje de registro se pasa como una cadena a estas funciones. Los niveles de registro son sugerencias. En última instancia, depende de usted decidir en qué categoría cae su mensaje de registro. Ingrese lo siguiente en el shell interactivo:

>>> import logging
>>> logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s -
%(levelname)s -  %(message)s')
>>> logging.debug('Some debugging details.')
2019-05-18 19:04:26,901 - DEBUG - Some debugging details.
>>> logging.info('The logging module is working.')
2019-05-18 19:04:35,569 - INFO - The logging module is working.
>>> logging.warning('An error message is about to be logged.')
2019-05-18 19:04:56,843 - WARNING - An error message is about to be logged.
>>> logging.error('An error has occurred.')
2019-05-18 19:05:07,737 - ERROR - An error has occurred.
>>> logging.critical('The program is unable to recover!')
2019-05-18 19:05:45,794 - CRITICAL - The program is unable to recover!

El beneficio de los niveles de registro es que puede cambiar la prioridad del mensaje de registro que desea ver. Pasar logging.DEBUG al argumento de palabra clave de nivel de la función basicConfig() mostrará mensajes de todos los niveles de registro (siendo DEBUG el nivel más bajo). Pero después de desarrollar su programa un poco más, es posible que solo le interesen los errores. En ese caso, puede establecer el argumento de nivel de basicConfig() en logging.ERROR. Esto mostrará solo mensajes de ERROR y CRITICAL y omitirá los mensajes DEBUG, INFO y WARNING.

Después de haber depurado su programa, probablemente no quiere que todos estos mensajes de registro saturen la pantalla. La función logging.disable() los desactiva para que no tengas que entrar en tu programa y eliminar todas las llamadas de registro a mano. Simplemente pasa a logging.disable() un nivel de registro, y suprimirá todos los mensajes de registro de ese nivel o inferior. Así que si quieres desactivar el registro por completo, sólo tienes que añadir logging.disable(logging.CRITICAL) a tu programa. Por ejemplo, introduzca lo siguiente en el shell interactivo:

>>> import logging
>>> logging.basicConfig(level=logging.INFO, format=' %(asctime)s -
%(levelname)s -  %(message)s')
>>> logging.critical('Critical error! Critical error!')
2019-05-22 11:10:48,054 - CRITICAL - Critical error! Critical error!
>>> logging.disable(logging.CRITICAL)
>>> logging.critical('Critical error! Critical error!')
>>> logging.error('Error! Error!')

Dado que logging.disable() deshabilitará todos los mensajes posteriores, probablemente desee agregarlo cerca de la línea de código de registro de importación en su programa. De esta manera, puede encontrarlo fácilmente para comentar o descomentar esa llamada para habilitar o deshabilitar el registro de mensajes según sea necesario.

En lugar de mostrar los mensajes de registro en la pantalla, puede escribirlos en un archivo de texto. La función logging.basicConfig() toma un argumento de palabra clave de nombre de archivo , así:

import logging
logging.basicConfig(filename='myProgramLog.txt', level=logging.DEBUG, format='%(asctime)s -  %(levelname)s -  %(message)s')

Los mensajes de registro se guardarán en myProgramLog.txt. Si bien los mensajes de registro son útiles, pueden abarrotar la pantalla y dificultar la lectura.la salida del programa. Escribir los mensajes de registro en un archivo mantendrá su pantalla despejada y almacenará los mensajes para que pueda leerlos después de ejecutar el programa. Puede abrir este archivo de texto en cualquier editor de texto, como Notepad o TextEdit.

Deja una respuesta