J'utilise python logger. Voici mon code:
import os
import time
import datetime
import logging
class Logger :
def myLogger(self):
logger = logging.getLogger('ProvisioningPython')
logger.setLevel(logging.DEBUG)
now = datetime.datetime.now()
handler=logging.FileHandler('/root/credentials/Logs/ProvisioningPython'+ now.strftime("%Y-%m-%d") +'.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
Le problème que j'ai est que j'obtiens plusieurs entrées dans le fichier journal pour chaque logger.info
appel. Comment puis-je resoudre ceci?
Réponses:
Le
logging.getLogger()
est déjà un singleton. ( Documentation )Le problème est que chaque fois que vous appelez
myLogger()
, cela ajoute un autre gestionnaire à l'instance, ce qui entraîne la duplication des journaux.Peut-être quelque chose comme ça?
la source
loggers.update(dict(name=logger))
? n'est pasloggers[name] = logger
plus simple?loggers.update(dict(name=logger))
créera un dictionnaire avec une seule clé appeléename
et mettra continuellement à jour cette même clé. Je suis surpris que personne n'ait mentionné cela plus tôt car ce code est assez cassé :) Apportera les modifications nécessaires.loggers
dictionnaire global n'est-il pas redondant aveclogging.getLogger
? puisque vous voulez vraiment simplement éviter d'ajouter des gestionnaires supplémentaires, il semble que vous préfériez les réponses ci-dessous qui vérifient directement les gestionnairesDepuis Python 3.2, vous pouvez simplement vérifier si les gestionnaires sont déjà présents et si c'est le cas, effacez-les avant d'ajouter de nouveaux gestionnaires. C'est assez pratique lors du débogage et le code inclut l'initialisation de votre enregistreur
la source
fait le truc pour moi
en utilisant python 2.7
la source
J'ai déjà utilisé le
logger
comme singleton et vérifiéif not len(logger.handlers)
, mais j'ai quand même eu des doublons : c'était la sortie formatée, suivie de la sortie non formatée.Solution dans mon cas:
logger.propagate = False
Crédits pour cette réponse et les documents .
la source
Vous appelez
Logger.myLogger()
plus d'une fois. Stockez l'instance de journalisation qu'elle renvoie quelque part et réutilisez -la .Sachez également que si vous vous connectez avant l'ajout d'un gestionnaire, une valeur par défaut
StreamHandler(sys.stderr)
sera créée.la source
Ceci est un ajout à la réponse de @ rm957377 mais avec une explication de pourquoi cela se produit . Lorsque vous exécutez une fonction lambda dans AWS, ils appellent votre fonction à partir d'une instance d'encapsulation qui reste active pendant plusieurs appels. Cela signifie que si vous appelez
addHandler()
dans le code de votre fonction, il continuera à ajouter des gestionnaires en double au singleton de journalisation à chaque exécution de la fonction. Le singleton de journalisation persiste pendant plusieurs appels de votre fonction lambda.Pour résoudre ce problème, vous pouvez effacer vos gestionnaires avant de les définir via:
la source
.info()
appel, ce que je ne comprends pas.Votre enregistreur doit fonctionner comme un singleton. Vous ne devriez pas le créer plus d'une fois. Voici un exemple à quoi cela pourrait ressembler:
la source
L'implémentation de logger est déjà un singleton.
Source - Utilisation de la journalisation dans plusieurs modules
Donc, la façon dont vous devriez l'utiliser est -
Supposons que nous ayons créé et configuré un logger appelé 'main_logger' dans le module principal (qui configure simplement le logger, ne renvoie rien).
Maintenant dans un sous-module, si nous créons un enregistreur enfant suivant la hiérarchie de dénomination 'main_logger.sub_module_logger' , nous n'avons pas besoin de le configurer dans le sous-module. La simple création de l'enregistreur suivant la hiérarchie de dénomination est suffisante.
Et cela n'ajoutera pas non plus de gestionnaire de doublons.
Voir cette question pour une réponse un peu plus détaillée.
la source
logger = logging.getLogger('my_logger') ; logger.handlers = [logger.handlers[0], ]
Une sortie de l'enregistreur double (ou triple ou ..- basée sur le nombre de recharges) peut également se produire lorsque vous rechargez votre module via
importlib.reload
(pour la même raison que celle expliquée dans la réponse acceptée). J'ajoute cette réponse juste pour une référence future car il m'a fallu un certain temps pour comprendre pourquoi ma sortie est dupliquée (triple) cated.la source
Une solution de contournement simple est comme
De cette façon, vous évitez d'ajouter un nouveau gestionnaire aux "gestionnaires" de la liste sous-jacente.
la source
En fin de compte, dans la plupart des cas, lorsque cela se produit, il suffit d'appeler logger.getLogger () une seule fois par module. Si vous avez plusieurs classes comme moi, je pourrais l'appeler ainsi:
Les deux auront alors leur propre nom de package complet et leur méthode d'enregistrement.
la source
Vous pouvez obtenir la liste de tous les gestionnaires pour l'enregistreur particulier, vous pouvez donc faire quelque chose comme ça
Dans l'exemple ci-dessus, nous vérifions si le gestionnaire d'un fichier spécifié est déjà connecté à l'enregistreur, mais avoir accès à la liste de tous les gestionnaires vous donne la possibilité de décider sur quels critères vous devez ajouter un autre gestionnaire ou non.
la source
Eu ce problème aujourd'hui. Puisque mes fonctions étaient @staticmethod, les suggestions ci-dessus ont été résolues avec random ().
Ressemblant à quelque chose comme:
la source
la source