De manière générale, le logging consiste à conserver un journal généré par un programme informatique. Un fichier journal (log) contient des enregistrements d'événements survenus dans votre code (par exemple, un code Python) ou votre système d'exploitation. Ces événements ou messages sont écrits dans un fichier de log ; un message ou un événement peut aussi représenter une interaction entre différents utilisateurs.
La façon de générer les logs dépend souvent des développeurs. Ils peuvent vouloir journaliser chaque opération d'une application, n'écrire que lorsqu'une erreur survient, ou encore suivre des opérations essentielles réalisées par un utilisateur. Une opération essentielle pourrait être d'identifier quel utilisateur final ou quelle adresse IP a accédé à l'application ou au serveur ; en cas de tentative infructueuse, le développeur peut alors s'appuyer sur les logs pour obtenir des informations plus précises qu'une simple pile d'appels.
Un bon exemple est lorsque vous essayez d'installer un paquet sur Linux avec sudo sans avoir les droits sudo. Vous voyez le message "Xyz is not in the sudoers file. This incident will be reported", qui est écrit dans un fichier de log.
La bonne nouvelle, c'est que Python inclut un module de logging prêt à l'emploi, sans installation supplémentaire.
En quoi le logging diffère-t-il d'une fonction print ?
Le logging est proche, dans l'esprit, d'une fonction print. Cependant, print ne fournit pas de nombreuses informations utiles au développeur. Le logging, lui, peut enregistrer l'horodatage et le numéro de ligne où l'erreur s'est produite. Il peut écrire des erreurs ou toute information dans des fichiers, des sockets, etc., et propose cinq niveaux de gravité pour différencier vos journaux.
Debug (10) : utile pour diagnostiquer les problèmes dans le code.
Info (20) : peut servir d'accusé de réception qu'aucun bug n'est présent dans le code. Un bon cas d'usage du niveau Info est le suivi de l'entraînement d'un modèle de machine learning.
Warning (30) : indique un problème potentiel à venir. Par exemple, l'avertissement d'un module qui pourrait être déprécié ou un avertissement de mémoire vive insuffisante.
Error (40) : un bug sérieux dans le code, comme une erreur de syntaxe, un dépassement mémoire, des exceptions.
Critical (50) : une erreur pouvant entraîner l'arrêt du programme ou une fin d'exécution brutale.
Assez de théorie, n'est-ce pas ?
Voyons maintenant comment implémenter le logging dans un code Python.
Mais avant cela, parcourons la table des attributs de logging, car vous utiliserez certains des attributs ci-dessous dans ce tutoriel.
logging.critical("A Critical Logging Message")Propulsé par
CRITICAL:root:A Critical Logging Message
Propulsé par
Comme vous pouvez le constater ci-dessus, seuls les messages dont la gravité est supérieure à 20 ont été effectivement journalisés, car c'est la configuration par défaut du logging en Python.
Cependant, comme indiqué plus haut, vous pouvez modifier les niveaux de gravité avec la méthode basicConfig(). Ici, vous passez le niveau de gravité à 20, ce qui signifie que les niveaux ayant une gravité supérieure à 10 seront logués.
Remarque : merci de redémarrer le noyau avant d'exécuter les cellules ci-dessous afin d'obtenir le bon résultat.
logging.basicConfig(level = logging.INFO, filename ='datacamp.log')Propulsé par
logging.debug("A Debug Logging Message")Propulsé par
logging.info("A Info Logging Message")Propulsé par
logging.warning("A Warning Logging Message")Propulsé par
logging.error("An Error Logging Message")Propulsé par
logging.critical("A Critical Logging Message")Propulsé par
Comme vous le voyez, les logs sont désormais générés dans le fichier datacamp.log. En exécutant les cellules ci-dessus plusieurs fois, vous constaterez que les entrées sont ajoutées au fichier à chaque exécution. Par défaut, le fichier est ouvert en mode append.
Vous pouvez utiliser le mot-clé filemode pour éviter que le fichier de log ne contienne des doublons (mode append). Passez le mode de fichier à write pour écraser les anciens logs et ne conserver que les plus récents. Comme filemode est défini sur w, le fichier de log sera ouvert en mode écriture à chaque appel à basicConfig(), ce qui finira par écraser le fichier.
Le fonctionnement du mode de fichier dans logging est similaire à la gestion standard des fichiers proposée par Python.
Exécutez plusieurs fois les lignes de code ci-dessus. Vous remarquerez que cette fois, seules les entrées courantes sont sauvegardées et les précédentes sont écrasées, comme ci-dessous.
Regardons d'autres attributs de logging comme la date, l'heure, et le numéro de ligne où l'avertissement ou l'erreur a été généré. Vous en conviendrez : ce sont autant d'atouts par rapport à un simple print, et le logging est bien plus puissant.
Pour ce faire, vous passerez les attributs asctime et lineno. Vous passerez aussi l'attribut message, qui sera l'emplacement réservé au texte que vous souhaitez afficher dans les logs. Tous ces attributs seront transmis au paramètre format.
Date-Time :2020-03-1823:58:12,429: Line No.:1-A Debug Logging Message
Date-Time :2020-03-1823:58:12,436: Line No.:2-A Info Logging Message
Date-Time :2020-03-1823:58:12,437: Line No.:3-A Warning Logging Message
Date-Time :2020-03-1823:58:12,440: Line No.:4- An Error Logging Message
Date-Time :2020-03-1823:58:12,441: Line No.:5-A Critical Logging Message
Propulsé par
Voyons les définitions de chaque attribut directement depuis ce tableau.
asctime : heure lisible par l'humain à laquelle le LogRecord a été généré. Par défaut, au format 2020-03-18 22:24:42,670 (les chiffres après la virgule sont les millisecondes). Comme il s'agit d'une chaîne, vous utilisez le spécificateur s après cet attribut.
lineno : numéro de ligne source où l'appel au logging a été effectué. Comme c'est un entier, vous utilisez le spécificateur d après cet attribut.
message : le message journalisé, calculé comme msg % args. Il est défini quand Formatter.format() est invoqué. Si vous ne précisez pas cet attribut via le paramètre format(), les messages que vous souhaitez consigner ne seront pas générés. De même, pour l'attribut message, vous utilisez s puisqu'il s'agit d'une chaîne.
funcName : affiche le nom du module ou de la fonction dans lequel le log est produit. Utile lorsque votre code comporte de nombreuses fonctions et que vous souhaitez regrouper les logs par fonction ou méthode.
Voyons un exemple simple pour remplacer print par logging dans une fonction de debug.
import logging
logging.basicConfig(format='%(asctime)s ::%(levelname)s ::%(funcName)s ::%(lineno)d \
::%(message)s', level = logging.INFO)defaddition(x, y):
add = x + y
return add
defsubtract(x, y):
sub = x - y
return sub
defmultiply(x, y):
mul = x * y
return mul
defdivide(x, y):
div = x / y
return div
defexponent(x, y):
exp = x ** y
return exp
num1 =20
num2 =2defmain():
add_result = addition(num1, num2)
logging.info('Add: {} + {} = {}'.format(num1, num2, add_result))
sub_result = subtract(num1, num2)
logging.info('Sub: {} - {} = {}'.format(num1, num2, sub_result))
mul_result = multiply(num1, num2)
logging.info('Mul: {} * {} = {}'.format(num1, num2, mul_result))
div_result = divide(num1, num2)
logging.info('Div: {} / {} = {}'.format(num1, num2, div_result))
exp_result = exponent(num1, num2)
logging.info('Exp: {} ** {} = {}'.format(num1, num2, exp_result))
main()Propulsé par
2020-03-1900:01:27,372::INFO:: main ::35:: Add:20+2=222020-03-1900:01:27,376::INFO:: main ::38:: Sub:20-2=182020-03-1900:01:27,377::INFO:: main ::41:: Mul:20*2=402020-03-1900:01:27,378::INFO:: main ::44:: Div:20/2=10.02020-03-1900:01:27,379::INFO:: main ::47:: Exp:20**2=400Propulsé par
Conclusion
Félicitations pour avoir terminé ce tutoriel.
N'hésitez pas à explorer d'autres attributs de logging et à voir comment les exploiter dans votre code.
Vous pouvez poser toutes vos questions liées à ce tutoriel dans la section des commentaires ci-dessous.
Initiez-vous aux structures de données de Python : apprenez-en plus sur les types de données et les structures de données primitives et non primitives, telles que les chaînes de caractères, les listes, les piles, etc.
Découvrez les fonctions et méthodes des listes Python. Veuillez suivre les exemples de code pour list() et d'autres fonctions et méthodes Python dès maintenant.
Tutoriel complet d'introduction aux boucles Python. Apprenez et pratiquez les boucles while et for, les boucles imbriquées, les mots-clés break et continue, la fonction range et bien plus encore.
Si vous débutez en Python et souhaitez aller plus loin, suivez le cours Introduction to Data Science in Python de DataCamp.
De manière générale, le logging consiste à conserver un journal généré par un programme informatique. Un fichier journal (log) contient des enregistrements d'événements survenus dans votre code (par exemple, un code Python) ou votre système d'exploitation. Ces événements ou messages sont écrits dans un fichier de log ; un message ou un événement peut aussi représenter une interaction entre différents utilisateurs.
La façon de générer les logs dépend souvent des développeurs. Ils peuvent vouloir journaliser chaque opération d'une application, n'écrire que lorsqu'une erreur survient, ou encore suivre des opérations essentielles réalisées par un utilisateur. Une opération essentielle pourrait être d'identifier quel utilisateur final ou quelle adresse IP a accédé à l'application ou au serveur ; en cas de tentative infructueuse, le développeur peut alors s'appuyer sur les logs pour obtenir des informations plus précises qu'une simple pile d'appels.
Un bon exemple est lorsque vous essayez d'installer un paquet sur Linux avec sudo sans avoir les droits sudo. Vous voyez le message "Xyz is not in the sudoers file. This incident will be reported", qui est écrit dans un fichier de log.
La bonne nouvelle, c'est que Python inclut un module de logging prêt à l'emploi, sans installation supplémentaire.
En quoi le logging diffère-t-il d'une fonction print ?
Le logging est proche, dans l'esprit, d'une
fonction print. Cependant, print ne fournit pas de nombreuses informations utiles au développeur. Le logging, lui, peut enregistrer l'horodatage et le numéro de ligne où l'erreur s'est produite. Il peut écrire des erreurs ou toute information dans des fichiers, des sockets, etc., et propose cinq niveaux de gravité pour différencier vos journaux.Les cinq niveaux de logging présentés ici sont :
Debug (10) : utile pour diagnostiquer les problèmes dans le code.
Info (20) : peut servir d'accusé de réception qu'aucun bug n'est présent dans le code. Un bon cas d'usage du niveau Info est le suivi de l'entraînement d'un modèle de machine learning.
Warning (30) : indique un problème potentiel à venir. Par exemple, l'avertissement d'un module qui pourrait être déprécié ou un avertissement de mémoire vive insuffisante.
Error (40) : un bug sérieux dans le code, comme une erreur de syntaxe, un dépassement mémoire, des exceptions.
Critical (50) : une erreur pouvant entraîner l'arrêt du programme ou une fin d'exécution brutale.
Assez de théorie, n'est-ce pas ?
Voyons maintenant comment implémenter le logging dans un code Python.
Mais avant cela, parcourons la table des attributs de logging, car vous utiliserez certains des attributs ci-dessous dans ce tutoriel.
Vous allez maintenant appeler la méthode
basicConfig(), qui crée une configuration de base pour que le système de logging fonctionne correctement.Elle permet de définir les paramètres suivants :
N'oubliez pas que la méthode
basicConfig()est facultative et que vous pouvez choisir de ne pas l'utiliser.Construisons maintenant les cinq niveaux de gravité.
Comme vous pouvez le constater ci-dessus, seuls les messages dont la gravité est supérieure à 20 ont été effectivement journalisés, car c'est la configuration par défaut du logging en Python.
Cependant, comme indiqué plus haut, vous pouvez modifier les niveaux de gravité avec la méthode
basicConfig(). Ici, vous passez le niveau de gravité à 20, ce qui signifie que les niveaux ayant une gravité supérieure à 10 seront logués.Remarque : merci de redémarrer le noyau avant d'exécuter les cellules ci-dessous afin d'obtenir le bon résultat.
Journalisons maintenant les sorties ci-dessus dans un fichier log. Pour cela, utilisez la méthode
basicConfig().Comme vous le voyez, les logs sont désormais générés dans le fichier
datacamp.log. En exécutant les cellules ci-dessus plusieurs fois, vous constaterez que les entrées sont ajoutées au fichier à chaque exécution. Par défaut, le fichier est ouvert en modeappend.Vous pouvez utiliser le mot-clé
filemodepour éviter que le fichier de log ne contienne des doublons (mode append). Passez le mode de fichier àwritepour écraser les anciens logs et ne conserver que les plus récents. Commefilemodeest défini surw, le fichier de log sera ouvert enmode écritureà chaque appel àbasicConfig(), ce qui finira par écraser le fichier.Le fonctionnement du mode de fichier dans logging est similaire à la gestion standard des fichiers proposée par Python.
Exécutez plusieurs fois les lignes de code ci-dessus. Vous remarquerez que cette fois, seules les entrées courantes sont sauvegardées et les précédentes sont écrasées, comme ci-dessous.
Regardons d'autres attributs de logging comme la date, l'heure, et le numéro de ligne où l'avertissement ou l'erreur a été généré. Vous en conviendrez : ce sont autant d'atouts par rapport à un simple print, et le logging est bien plus puissant.
Pour ce faire, vous passerez les attributs
asctimeetlineno. Vous passerez aussi l'attributmessage, qui sera l'emplacement réservé au texte que vous souhaitez afficher dans les logs. Tous ces attributs seront transmis au paramètreformat.Voyons les définitions de chaque attribut directement depuis ce tableau.
asctime: heure lisible par l'humain à laquelle le LogRecord a été généré. Par défaut, au format2020-03-18 22:24:42,670(les chiffres après la virgule sont les millisecondes). Comme il s'agit d'une chaîne, vous utilisez le spécificateursaprès cet attribut.lineno: numéro de ligne source où l'appel au logging a été effectué. Comme c'est un entier, vous utilisez le spécificateurdaprès cet attribut.message: le message journalisé, calculé comme msg % args. Il est défini quandFormatter.format()est invoqué. Si vous ne précisez pas cet attribut via le paramètre format(), les messages que vous souhaitez consigner ne seront pas générés. De même, pour l'attribut message, vous utilisezspuisqu'il s'agit d'une chaîne.funcName: affiche le nom du module ou de la fonction dans lequel le log est produit. Utile lorsque votre code comporte de nombreuses fonctions et que vous souhaitez regrouper les logs par fonction ou méthode.Voyons un exemple simple pour remplacer print par logging dans une fonction de debug.
Conclusion
Félicitations pour avoir terminé ce tutoriel.
N'hésitez pas à explorer d'autres attributs de logging et à voir comment les exploiter dans votre code.
Vous pouvez poser toutes vos questions liées à ce tutoriel dans la section des commentaires ci-dessous.
Si vous débutez en Python et souhaitez en apprendre davantage, suivez le cours Introduction to Data Science in Python de DataCamp.