J'aimerais avoir le niveau de log TRACE (5) pour mon application, car je ne pense pas que ce debug()
soit suffisant. Ce log(5, msg)
n'est pas non plus ce que je veux. Comment puis-je ajouter un niveau de journalisation personnalisé à un enregistreur Python?
J'ai un mylogger.py
avec le contenu suivant:
import logging
@property
def log(obj):
myLogger = logging.getLogger(obj.__class__.__name__)
return myLogger
Dans mon code, je l'utilise de la manière suivante:
class ExampleClass(object):
from mylogger import log
def __init__(self):
'''The constructor with the logger'''
self.log.debug("Init runs")
Maintenant j'aimerais appeler self.log.trace("foo bar")
Merci d'avance pour votre aide.
Edit (8 décembre 2016): J'ai changé la réponse acceptée en pfa qui est, à mon humble avis , une excellente solution basée sur la très bonne proposition d'Eric S.
la source
logging.DEBUG_LEVEL_NUM = 9
pour pouvoir accéder à ce niveau de débogage partout où vous importez le logger dans votre code?DEBUG_LEVEL_NUM = 9
vous devriez définirlogging.DEBUG_LEVEL_NUM = 9
. De cette façon, vous pourrez utiliserlog_instance.setLevel(logging.DEBUG_LEVEL_NUM)
la même manière que vous en utilisant right knowlogging.DEBUG
oulogging.INFO
logging.DEBUGV = DEBUG_LEVELV_NUM
etlogging.__all__ += ['DEBUGV']
La seconde n'est pas très importante mais la première est nécessaire si vous avez un code qui ajuste dynamiquement le niveau de journalisation et que vous voulez pouvoir faire quelque chose commeif verbose: logger.setLevel(logging.DEBUGV)
``J'ai pris la réponse "éviter de voir lambda" et j'ai dû modifier l'endroit où le log_at_my_log_level était ajouté. J'ai aussi vu le problème que Paul a fait "Je ne pense pas que cela fonctionne. N'avez-vous pas besoin de logger comme premier argument dans log_at_my_log_level?" Cela a fonctionné pour moi
la source
__init__.py
et soyez heureux: DTypeError: not all arguments converted during string formatting
mais ça marche bien avec *. (Python 3.4.3). Est-ce un problème de version de Python ou quelque chose qui me manque?AttributeError: module 'logging' has no attribute 'debugv'
En combinant toutes les réponses existantes avec un tas d'expérience d'utilisation, je pense avoir dressé une liste de toutes les choses à faire pour assurer une utilisation totalement transparente du nouveau niveau. Les étapes ci-dessous supposent que vous ajoutez un nouveau niveau
TRACE
avec une valeurlogging.DEBUG - 5 == 5
:logging.addLevelName(logging.DEBUG - 5, 'TRACE')
doit être invoqué pour que le nouveau niveau soit enregistré en interne afin qu'il puisse être référencé par son nom.logging
lui - même pour la cohérence:logging.TRACE = logging.DEBUG - 5
.trace
doit être ajoutée aulogging
module. Il doit se comporter commedebug
,info
, etc.trace
doit être ajoutée à la classe de journalisation actuellement configurée. Comme ce n'est pas garanti à 100%logging.Logger
, utilisezlogging.getLoggerClass()
plutôt.Toutes les étapes sont illustrées dans la méthode ci-dessous:
la source
Oldest
, et vous comprendrez que c'est la meilleure de toutes!args
dans lalogForLevel
mise en œuvre est-elle intentionnelle / requise?Cette question est assez ancienne, mais je viens de traiter le même sujet et j'ai trouvé une voie similaire à celles déjà évoquées qui me paraît un peu plus propre. Cela a été testé sur 3.4, donc je ne suis pas sûr que les méthodes utilisées existent dans les anciennes versions:
la source
get
etsetLoggerClass
faire exactement et pourquoi ils sont nécessaires?TRACE
niveau à la bibliothèque de journalisation par défaut. +1Qui a commencé la mauvaise pratique d'utiliser des méthodes internes (
self._log
) et pourquoi chaque réponse est-elle basée sur cela?! La solution pythonique serait d'utiliser à laself.log
place pour ne pas avoir à jouer avec des trucs internes:la source
Je trouve plus facile de créer un nouvel attribut pour l'objet enregistreur qui passe la fonction log (). Je pense que le module logger fournit le addLevelName () et le log () pour cette raison même. Ainsi, aucune sous-classe ou nouvelle méthode n'est nécessaire.
maintenant
devrait fonctionner comme prévu.
la source
_log
, nonlog
.Bien que nous ayons déjà beaucoup de réponses correctes, ce qui suit est à mon avis plus pythonique:
Si vous souhaitez utiliser
mypy
sur votre code, il est recommandé d'ajouter# type: ignore
pour supprimer les avertissements d'ajout d'attribut.la source
logging.trace = partial(logging.log, logging.TRACE) # type: ignore
?Je pense que vous devrez sous-
Logger
classer la classe et ajouter une méthode appeléetrace
qui appelle essentiellementLogger.log
avec un niveau inférieur àDEBUG
. Je n'ai pas essayé cela, mais c'est ce que la documentation indique .la source
logging.getLogger
pour renvoyer votre sous-classe au lieu de la classe intégrée.setLoggerClass(MyClass)
puis appelergetLogger()
comme d'habitude ...Conseils pour créer un enregistreur personnalisé:
_log
, utiliserlog
(vous n'avez pas à vérifierisEnabledFor
)getLogger
, vous devrez donc définir la classe viasetLoggerClass
__init__
pour l'enregistreur, la classe si vous ne stockez rienLorsque vous appelez cet enregistreur, utilisez
setLoggerClass(MyLogger)
pour en faire l'enregistreur par défaut degetLogger
Vous aurez besoin de
setFormatter
,setHandler
etsetLevel(TRACE)
sur lehandler
et surlog
lui - même pour voir réellement cette trace de bas niveaula source
Cela a fonctionné pour moi:
Le problème lambda / funcName est résolu avec logger._log comme @marqueed l'a souligné. Je pense que l'utilisation de lambda semble un peu plus propre, mais l'inconvénient est qu'il ne peut pas prendre d'arguments de mots-clés. Je n'ai jamais utilisé ça moi-même, donc pas de problème.
la source
D'après mon expérience, c'est la solution complète au problème de l'op ... pour éviter de voir "lambda" comme la fonction dans laquelle le message est émis, allez plus loin:
Je n'ai jamais essayé de travailler avec une classe de journalisation autonome, mais je pense que l'idée de base est la même (utilisez _log).
la source
logger
comme premier argumentlog_at_my_log_level
?Exemple d'ajout à Mad Physicists pour obtenir le nom de fichier et le numéro de ligne corrects:
la source
basé sur une réponse épinglée, j'ai écrit une petite méthode qui crée automatiquement de nouveaux niveaux de journalisation
config peut ressembler à ça:
la source
Au lieu d'ajouter une méthode supplémentaire à la classe Logger, je recommanderais d'utiliser la
Logger.log(level, msg)
méthode.la source
Je suis confus; avec python 3.5, au moins, cela fonctionne:
production:
la source
logger.trace('hi')
que je crois être l'objectif principalAu cas où quelqu'un souhaiterait un moyen automatisé d'ajouter un nouveau niveau de journalisation au module de journalisation (ou à une copie de celui-ci) de manière dynamique, j'ai créé cette fonction, en développant la réponse de @ pfa:
la source
setattr
place ...