Python journalisation dans Django
Je suis l'élaboration d'un Django app, et je suis en train d'utiliser Python module de journalisation pour l'erreur/l'enregistrement des traces. Idéalement, j'aimerais avoir différents enregistreurs configuré pour différentes zones du site. Jusqu'à présent, j'ai tout de ce travail, mais une chose m'a me gratter la tête.
J'ai la racine enregistreur va sys.stderr, et j'ai configuré un autre enregistreur pour écrire dans un fichier. C'est dans ma settings.py fichier:
sviewlog = logging.getLogger('MyApp.views.scans')
view_log_handler = logging.FileHandler('C:\\MyApp\\logs\\scan_log.log')
view_log_handler.setLevel(logging.INFO)
view_log_handler.setFormatter(logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s'))
sviewlog.addHandler(view_log_handler)
Semble assez simple. Voici le problème, cependant: ce que j'écris à la sviewlog est écrit dans le fichier journal deux fois. La racine de l'enregistreur imprime seulement une fois. C'est comme addHandler() est appelée deux fois. Et quand j'ai mis mon code par le biais d'un débogueur, c'est exactement ce que je vois. Le code de la settings.py est d'obtenir exécutée deux fois, donc deux FileHandlers sont créés et ajoutés à la même enregistreur de données d'instance. Mais pourquoi? Et comment puis-je contourner ce problème?
Quelqu'un peut me dire ce qu'il se passe ici? J'ai essayé de déplacer le sviewlog enregistreur/gestionnaire de l'instanciation de code pour le fichier dans lequel il est utilisé (car il semble effectivement comme l'endroit le plus approprié pour moi), mais j'ai le même problème. La plupart des exemples que j'ai vu en ligne, utilisez uniquement la racine de l'enregistreur, et je préfère avoir plusieurs enregistreurs.
Vous devez vous connecter pour publier un commentaire.
Permettez-moi de répondre à ma propre question. Le problème sous-jacent ici est que settings.py importés par deux fois, ou peut-être même plus (Voir ici). (Je ne comprends toujours pas pourquoi c'est. Peut-être que certains Django expert pourrait m'expliquer cela.) Cela semble être le cas pour certains autres modules. À ce stade, je ne pense pas qu'il est sage de faire des hypothèses sur la façon dont de nombreuses fois settings.py seront importés. D'ailleurs, de telles hypothèses ne sont pas en sécurité en général. J'ai eu ce code dans les lieux autres que les settings.py et les résultats sont similaires.
Vous avez le code autour de ce. Qui est, vous devez vérifier votre enregistreur pour les gestionnaires avant d'ajouter d'autres gestionnaires d'elle. C'est un peu moche car il est parfaitement raisonnable d'avoir plusieurs maîtres-chiens-même du même type -- relié à un enregistreur. Il existe quelques solutions pour régler ce problème. L'un est de vérifier les gestionnaires de la propriété de votre objet logger. Si vous voulez seulement un maître-chien et de votre length > 0, alors ne pas l'ajouter. Personnellement, je n'aime pas cette solution, car il est malpropre avec plus de gestionnaires.
Je préfère quelque chose comme cela (merci à Thomas Guettler):
Je dois dire, je souhaite le fait que Django importations settings.py plusieurs fois ont été mieux documentées. Et j'imagine que ma configuration est en quelque sorte la cause de cette plusieurs importation, mais je vais avoir du mal à trouver ce qui cause le problème et pourquoi. Peut-être que je ne pouvais pas trouver que dans leurs documents, mais je pense que c'est le genre de chose que vous devez avertir vos utilisateurs.
À partir de la version 1.3, Django utilise la norme python journalisation, configuré avec le
LOGGING
paramètre (documentée ici: 1.3, dev).Django journalisation de référence: 1.3, dev.
Difficile de se prononcer sur votre cas particulier. Si settings.py est exécutée deux fois, alors il est normal que vous obtenez deux lignes pour chaque journal a envoyé.
Nous avons eu le même problème, donc nous l'avons créé dans nos projets pour avoir un module dédié à l'exploitation forestière. Que les modules a un module "singleton" modèle, de sorte que nous n'exécuter les codes intéressants une fois.
Il ressemble à ceci:
De l'importation de la log.py la première fois configurer la journalisation correctement.
import log, logging
que d'écrire smthng commelogger = logging.getLogger(LOG_AREA1)
et seulement ensuite l'utiliser commelogger.info(bla-bla-bla)
? Est-il mieux de retourner enregistreur de données de init_logging() (return logging.getLogger...
) et activez le module var? Direlogger = init_logging()
. De cette façon, vous pouvez importer log.py et juste de commencer à l'utiliserimport log; log.logger.info(bla-bla-bla)
?import log; module_logger = log.logger.getLogger(__name__)
logInitDone
truc est inutile. Regardez, lorsqu'il est exécuté deux foislogInitDone
reprend toujoursFalse
doncinit_logging()
serait encore appelé deux fois. Cela ne fonctionne que parce que le module n'est jamais exécutée une seule fois tandis que les importations comme expliqué dans cette réponse.Faire revivre un vieux thread, mais je vivais les messages en double lors de l'utilisation de Django 1.3 Python journalisation avec les dictConfig format.
La
disable_existing_loggers
se débarrasse de la double gestionnaire de journalisation/problème avec plusieurs settings.py les charges, mais vous pouvez toujours obtenir un double des messages de journal si vous ne spécifiez pas lepropagate
booléenne de manière appropriée sur leslogger
. À savoir, assurez-vous de définirpropagate=False
pour enfant bûcherons. E. g.,Ici,
project.customapp
jeux depropagate=False
afin de ne pas être pris par lesproject
logger en tant que bien. Le Django journalisation des docs sont excellents, comme toujours.En fait, elle ne l'importation de deux fois (passer le premier morceau de code pour obtenir le droit dans les détails, mais une bonne lecture si vous avez le temps):
http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html
PS– Désolé de relancer un vieux thread.
Vous pourriez obtenir autour de votre problème en vérifiant le nombre de gestionnaires d'lorsque vous faites votre init.
Je ne pense pas que c'est une excellente façon de le gérer. Personnellement, pour l'enregistrement de django reinhardt avec le python module de journalisation, j'ai créer un enregistreur views.py pour chaque application, je suis intéressé par, puis saisir le logger dans chaque vue de la fonction.
C'est un très bon article sur le débogage de django et couvre une partie de la journalisation:
http://simonwillison.net/2008/May/22/debugging/
Pour répondre à la question sur pourquoi "Django importations settings.py plusieurs fois": il ne l'est pas.
Vous êtes probablement à l'exécution d'un multi process/multithread serveur web qui crée de nombreuses python sous-interprètes, où chacun de ces importations le code de votre django app une fois.
Test que sur la django serveur de test et vous devriez voir que les paramètres ne sont pas importées de nombreuses fois.
Il y a quelques temps, j'avais conçu une belle singleton (python borg idiome version pour être plus précis) avec mon premier django/apache application, avant je me suis vite rendu compte que oui, j'ai eu plus d'une des instances de mon singleton créé...
Vous pouvez également utiliser une fois Middleware pour obtenir un effet similaire, sans les variables privées. Notez que cela ne configurer l'enregistrement pour le web-demandes - vous aurez besoin de trouver une autre solution si vous voulez l'exploitation forestière dans votre shell ou de la commande s'exécute.
Pourquoi à l'aide de python enregistreur au lieu de django d'enregistrement? L'essayer, c'est peut résoudre votre problème.
http://code.google.com/p/django-logging/wiki/Overview
À ce moment, ce serait seulement permettent d'afficher la racine logger, mais bien sûr, vous pouvez écrire à plusieurs enregistreurs.
Un hackish chemin, mais vous pouvez essayer de mettre le code d'enregistrement à l'intérieur d'un admin.py. Il est censé être importés qu'une seule fois.
Sinon, pouvez vous vérifiez d'abord si
MyApp.views.scans
journal existe? Si il existe (peut-être une erreur est déclenchée), vous pouvez tout simplement ignorer la création (et donc de ne pas ajouter le gestionnaire de nouveau). D'une façon plus propre, mais je n'ai pas essayé cette même si.Aussi il doit y avoir un endroit plus approprié pour mettre ce code (
__init__.py
?).settings.py
est pour les paramètres.À ajouter à Un Lee post, python journalisation des états de documentation à ce sujet de se propager:
Cela signifie que si
propagate == False
puis enfant enregistreur de de ne PAS passer à la journalisation des messages à ses parent enregistreur de