À l'aide de Python journalisation dans plusieurs modules
J'ai un petit projet de python qui a la structure suivante -
Project
-- pkg01
-- test01.py
-- pkg02
-- test02.py
-- logging.conf
J'ai l'intention d'utiliser la journalisation par défaut un module pour imprimer les messages sur la sortie standard, et un fichier journal.
Pour utiliser le module de journalisation, certains d'initialisation est nécessaire -
import logging.config
logging.config.fileConfig('logging.conf')
logger = logging.getLogger('pyApp')
logger.info('testing')
À l'heure actuelle, j'ai effectuer cette initialisation dans chaque module avant de commencer la journalisation des messages. Est-il possible d'effectuer cette initialisation qu'une seule fois à un endroit, que les mêmes paramètres sont réutilisés par l'exploitation forestière à travers tout le projet?
- En réponse à votre commentaire sur ma réponse: vous n'avez pas à appeler
fileConfig
dans chaque module de journalisation, sauf si vous avezif __name__ == '__main__'
logique dans chacun d'eux. prost réponse n'est pas une bonne pratique si le package est une bibliothèque, mais il pourrait travailler pour vous - il ne faut pas configurer la journalisation dans les paquets de bibliothèque, autres que pour ajouter unNullHandler
. - prost implicite que nous devons appeler l'importation et l'enregistreur de stmts dans chaque module, et appeler l'fileconfig stmt dans le module principal. nest pas similaire à ce que vous dites?
- prost est en train de dire que vous devriez mettre la journalisation config code dans
package/__init__.py
. Ce n'est pas normalement l'endroit où vous mettreif __name__ == '__main__'
code. Aussi, prost exemple dirait qu'il va appeler la config code sans condition à l'importation, ce qui n'est pas bon pour moi. Généralement, l'exploitation forestière config code doit être fait en un seul endroit et ne devrait pas se produire comme effet secondaire de l'importation, sauf lorsque vous importez __principaux__. - vous avez raison, j'ai totalement raté la ligne "# package/__init__.py " dans son code de l'échantillon. merci pour le signaler et votre patience.
- Donc ce qui arrive si vous avez plusieurs
if __name__ == '__main__'
? (il n'est pas mentionné explicitement dans la question si c'est le cas)
Vous devez vous connecter pour publier un commentaire.
La meilleure pratique est, dans chaque module, d'avoir un enregistreur définie comme ceci:
près de la partie supérieure du module, puis dans un autre code dans le module n'par exemple
Si vous avez besoin de subdiviser les activités d'exploitation forestière à l'intérieur d'un module, utiliser, par exemple,
et journal de
loggerA
etloggerB
appropriées.Dans votre programme principal ou de programmes, de faire par exemple:
ou
Voir ici pour l'enregistrement de plusieurs modules, et ici pour la configuration de la journalisation pour le code qui sera utilisé comme un module de la bibliothèque par un autre code.
Mise à jour: Lors de l'appel de
fileConfig()
, vous pouvez spécifierdisable_existing_loggers=False
si vous êtes à l'aide de Python 2.6 ou version ultérieure (voir les docs pour plus d'informations). La valeur par défaut estTrue
pour des raisons de compatibilité ascendante, ce qui provoque tous les enregistreurs être désactivée parfileConfig()
à moins qu'ils ou leur ancêtre sont explicitement nommées dans la configuration. Avec la valeur de la valeurFalse
, existant bûcherons sont laissés seuls. Si à l'aide de Python 2.7 et Python 3.2 ou version ultérieure, vous pouvez envisager de ladictConfig()
API qui est mieux quefileConfig()
car il donne plus de contrôle sur la configuration.disable_existing_loggers
drapeau qui estTrue
par défaut mais peut êtreFalse
.disable_existing_loggers
. Vous pouvez vérifier lapydoc
ou de la source pour se rassurer qu'il n'a, en fait, existent dans cette version.With the value set to False, existing loggers are left alone
. Est-ce à dire défini précédemment enregistreur peut également charger les paramètres d'dictConfig()
qui sont invoquées plus tard?logger = logging.getLogger('flask.app')
est-il un moyen de le faire fonctionner avec__name__
? mon flacon application est également configuré avec__name__
:app = Flask(__name__)
__name__
pour l'enregistreur? Si c'est par exemplefoo.bar
, vous devez veiller à ce que les gestionnaires sont configurés pour enregistreurs defoo.bar
,foo
ou de la racine de l'enregistreur.En fait, tous les logger est un enfant de la mère du package enregistreur (c'est à dire
package.subpackage.module
hérite depackage.subpackage)
, de sorte que tous vous avez besoin à faire est de configurer la racine de l'enregistreur. Ceci peut être réalisé parjournalisation.config.fileConfig
(votre propre config pour les bûcherons) oujournalisation.basicConfig
(définit la racine de l'enregistreur). Journalisation de l'installation de votre module d'entrée (__main__.py
ou ce que vous souhaitez exécuter, par exemplemain_script.py
.__init__.py
fonctionne aussi bien)à l'aide de basicConfig:
à l'aide de fileConfig:
et puis créer chaque enregistreur à l'aide de:
Pour plus d'informations, voir Enregistrement Avancé Tutoriel.
__main__.py
(par exemple, Si je veux utiliser le module dans un script qui n'a pas d'enregistreur) seralogging.getLogger(__name__)
encore faire une sorte de journalisation dans le module ou il va lever une exception?if logging.getLogger(__name__): ... else: logging.basicConfig(... )
?Je fais toujours comme ci-dessous.
Utiliser un seul fichier python pour config mon journal comme le pattern singleton qui l'a nommé '
log_conf.py
'Dans un autre module, il suffit d'importer le fichier config.
C'est un singleton pour vous connecter, simplement et efficacement.
Plusieurs de ces réponses suggèrent que dans le haut d'un module que vous vous n'avez
C'est ma compréhension que cela est considéré comme très mauvaise pratique. La raison en est que le fichier de config va désactiver tous les enregistreurs par défaut. E. g.
Et dans votre module principal :
Maintenant le journal spécifié lors de l'enregistrement.ini est vide, l'enregistreur a été désactivé par fileconfig appel.
Tout est est certainement possible de contourner ce problème (disable_existing_Loggers=False), de façon réaliste, de nombreux clients de votre bibliothèque ne sais pas à propos de ce comportement, et de ne pas recevoir vos journaux. Le rendre facile pour vos clients toujours à l'appel de l'enregistrement.getLogger localement. Chapeau Astuce : j'ai appris à propos de ce comportement de Victor Lin de Site web.
Les bonnes pratiques est au lieu de toujours faire appel à la journalisation.getLogger localement. E. g.
Aussi, si vous utilisez fileconfig dans votre main, jeu de disable_existing_loggers=False, juste au cas où votre bibliothèque, les concepteurs utilisent le niveau de module enregistreur de cas.
logging.config.fileConfig('logging.ini')
avantimport my_module
? Comme l'a suggéré dans cette réponse.disable_existing_loggers=True
je serai très surpris de découvrir que vous ignorer et encore journal de.Lancer dans une autre solution.
Dans mon module de init.py j'ai quelque chose comme:
Puis dans chaque module, j'ai besoin d'un enregistreur, je n':
Lorsque les journaux sont manqués, vous pouvez différencier leur source par le module de provenance.
@Yarkee la solution semblait aller mieux. Je voudrais ajouter somemore à elle -
Donc LoggerManager peut être un enfichables pour l'ensemble de l'application.
Espérons que cela a du sens et de la valeur.
Vous pouvez également venir avec quelque chose de ce genre!
Maintenant, vous pouvez utiliser plusieurs enregistreurs de même module et à travers tout le projet si le ci-dessus est définie dans un module séparé et importés dans d'autres modules ont été la journalisation est nécessaire.
Il y a plusieurs réponses. j'ai fini avec une similaires, mais différentes, solution qui fait sens pour moi, peut-être que ça aura du sens pour vous.
Mon principal objectif était d'être en mesure de passer à des journaux, à des gestionnaires de par leur niveau (niveau de débogage journaux de la console, les avertissements et les ci-dessus pour les fichiers):
créé une belle util fichier nommé logger.py:
le flacon.app est une valeur codée en dur dans le flacon. l'application enregistreur est toujours en commençant par flacon.application comme le module du même nom.
maintenant, dans chaque module, je suis en mesure de l'utiliser dans le mode suivant:
Cela va créer un nouveau journal pour "app.flacon.NOM_DU_MODULE" avec un minimum d'effort.
La meilleure pratique serait de créer un module séparément qui n'a qu'une méthode dont la tâche serait de donner un enregistreur de gestionnaire à l'appel de la méthode. Enregistrez ce fichier en tant que m_logger.py
Maintenant appeler les getlogger() la méthode à chaque fois que l'enregistreur de gestionnaire est nécessaire.
--debug
option dans l'application et que vous voulez définir le niveau de journalisation dans tous bûcherons dans votre application basée sur ce paramètre...get_logger(level=logging.INFO)
pour retourner une sorte de singleton, donc, quand il appelle le premier temps de l'application principale, il initialise l'enregistreur de données et les gestionnaires d'avec le bon niveau, puis renvoie le mêmelogger
objet de toutes les autres méthodes.