J'ai un petit projet python qui a la structure suivante -
Project
-- pkg01
-- test01.py
-- pkg02
-- test02.py
-- logging.conf
J'ai l'intention d'utiliser le module de journalisation par défaut pour imprimer des messages sur stdout et un fichier journal. Pour utiliser le module de journalisation, une certaine initialisation est requise -
import logging.config
logging.config.fileConfig('logging.conf')
logger = logging.getLogger('pyApp')
logger.info('testing')
À l'heure actuelle, j'effectue cette initialisation dans chaque module avant de commencer la journalisation des messages. Est-il possible d'effectuer cette initialisation une seule fois au même endroit de sorte que les mêmes paramètres soient réutilisés en se connectant sur tout le projet?
fileConfig
tous les modules qui se connectent, sauf si vous avez de laif __name__ == '__main__'
logique dans chacun d'eux. La réponse de prost n'est pas une bonne pratique si le package est une bibliothèque, bien que cela puisse fonctionner pour vous - il ne faut pas configurer la journalisation dans les packages de bibliothèque, sauf pour ajouter unNullHandler
.package/__init__.py
. Ce n'est normalement pas l'endroit où vous mettez duif __name__ == '__main__'
code. En outre, l'exemple de prost semble appeler le code de configuration sans condition lors de l'importation, ce qui ne me semble pas correct. En règle générale, la journalisation du code de configuration doit être effectuée au même endroit et ne doit pas se produire comme effet secondaire de l'importation, sauf lorsque vous importez __main__.if __name__ == '__main__'
? (il n'est pas mentionné explicitement en question si tel est le cas)Réponses:
La meilleure pratique consiste, dans chaque module, à avoir un enregistreur défini comme ceci:
près du haut du module, puis dans un autre code du module, par exemple
Si vous devez subdiviser l'activité de journalisation à l'intérieur d'un module, utilisez par exemple
et connectez-vous
loggerA
etloggerB
selon le cas.Dans votre ou vos programmes principaux, faites par exemple:
ou
Voir ici pour la journalisation à partir de plusieurs modules, et ici pour la configuration de la journalisation du code qui sera utilisé comme module de bibliothèque par un autre code.
Mise à jour: lors de l'appel
fileConfig()
, vous souhaiterez peut-être spécifierdisable_existing_loggers=False
si vous utilisez Python 2.6 ou version ultérieure (consultez la documentation pour plus d'informations). La valeur par défaut estTrue
pour la compatibilité descendante, ce qui entraîne la désactivation de tous les enregistreurs existants àfileConfig()
moins qu'eux-mêmes ou leur ancêtre ne soient explicitement nommés dans la configuration. Avec la valeur définie surFalse
, les enregistreurs existants sont laissés seuls. Si vous utilisez Python 2.7 / Python 3.2 ou version ultérieure, vous souhaiterez peut-être envisager l'dictConfig()
API qui est meilleure quefileConfig()
car elle donne plus de contrôle sur la configuration.la source
disable_existing_loggers
indicateur qui estTrue
par défaut mais peut être défini surFalse
.En fait, chaque enregistreur est un enfant de l'enregistreur de packages du parent (c'est-à-dire qu'il
package.subpackage.module
hérite de la configurationpackage.subpackage)
, donc tout ce que vous devez faire est simplement de configurer l'enregistreur racine. Ceci peut être réalisé parlogging.config.fileConfig
(votre propre configuration pour les enregistreurs) oulogging.basicConfig
(définit l'enregistreur racine) . Configuration de la journalisation dans votre module d'entrée (__main__.py
ou tout ce que vous voulez exécuter, par exemplemain_script.py
.__init__.py
Fonctionne également)en utilisant basicConfig:
en utilisant fileConfig:
puis créez chaque enregistreur en utilisant:
Pour plus d'informations, voir Tutoriel de journalisation avancée .
la source
__main__.py
(par exemple, si je veux utiliser le module dans un script qui n'a pas d'enregistreur), fera-t-logging.getLogger(__name__)
il quand même une sorte d'enregistrement dans le module ou déclenchera-t-il une exception?Je le fais toujours comme ci-dessous.
Utilisez un seul fichier python pour configurer mon journal en tant que modèle singleton qui a nommé '
log_conf.py
'Dans un autre module, importez simplement la configuration.
Il s'agit d'un modèle singleton à enregistrer, simplement et efficacement.
la source
Plusieurs de ces réponses suggèrent qu'en haut d'un module, vous
Je crois comprendre que cela est considéré comme une très mauvaise pratique . La raison en est que la configuration du fichier désactivera tous les enregistreurs existants par défaut. Par exemple
Et dans votre module principal:
Maintenant, le journal spécifié dans logging.ini sera vide, car l'enregistreur existant a été désactivé par l'appel fileconfig.
Bien qu'il soit certainement possible de contourner ce problème (disable_existing_Loggers = False), de manière réaliste, de nombreux clients de votre bibliothèque ne seront pas au courant de ce comportement et ne recevront pas vos journaux. Facilitez la tâche de vos clients en appelant toujours logging.getLogger localement. Astuce: j'ai appris ce comportement sur le site Web de Victor Lin .
La bonne pratique consiste donc à toujours appeler localement logging.getLogger. Par exemple
De plus, si vous utilisez fileconfig dans votre main, définissez disable_existing_loggers = False, juste au cas où vos concepteurs de bibliothèque utiliseraient des instances de journalisation au niveau du module.
la source
logging.config.fileConfig('logging.ini')
avantimport my_module
? Comme suggéré dans cette réponse .logger = logging.getLogger(__name__)
''Une façon simple d'utiliser une instance de bibliothèque de journalisation dans plusieurs modules pour moi était la solution suivante:
base_logger.py
Autres fichiers
la source
Jeter une autre solution.
Dans l' initialisation de mon module, j'ai quelque chose comme:
Ensuite, dans chaque module, j'ai besoin d'un enregistreur, je fais:
Lorsque les journaux sont manqués, vous pouvez différencier leur source par le module dont ils sont issus.
la source
Vous pouvez également proposer quelque chose comme ça!
Vous pouvez maintenant utiliser plusieurs enregistreurs dans le même module et sur l'ensemble du projet si ce qui précède est défini dans un module distinct et importé dans d'autres modules si la journalisation est requise.
la source
@ La solution de Yarkee semblait meilleure. Je voudrais y ajouter encore plus -
LoggerManager peut donc être enfichable à l'ensemble de l'application. J'espère que cela a du sens et de la valeur.
la source
Il y a plusieurs réponses. je me suis retrouvé avec une solution similaire mais différente qui a du sens pour moi, peut-être qu'elle vous plaira aussi. Mon objectif principal était de pouvoir transmettre des logs aux gestionnaires par leur niveau (debug level logs à la console, avertissements et surtout aux fichiers):
créé un joli fichier util nommé logger.py:
flask.app est une valeur codée en dur dans flask. l'enregistreur d'applications commence toujours par flask.app comme nom du module.
maintenant, dans chaque module, je peux l'utiliser dans le mode suivant:
Cela va créer un nouveau journal pour "app.flask.MODULE_NAME" avec un minimum d'effort.
la source
La meilleure pratique serait de créer un module séparément qui n'a qu'une seule méthode dont la tâche consiste à donner un gestionnaire d'enregistreur à la méthode appelante. Enregistrez ce fichier sous m_logger.py
Appelez maintenant la méthode getlogger () chaque fois que le gestionnaire de l'enregistreur est nécessaire.
la source
--debug
option dans l'application et que vous souhaitez définir le niveau de journalisation dans tous les enregistreurs de votre application en fonction de ce paramètre ...get_logger(level=logging.INFO)
pour retourner une sorte de singleton, donc quand il a appelé pour la première fois depuis l'application principale, il initialise l'enregistreur et les gestionnaires avec le niveau approprié, puis renvoie le mêmelogger
objet à toutes les autres méthodes.Nouveau sur python, donc je ne sais pas si cela est conseillé, mais cela fonctionne très bien pour ne pas réécrire le passe-partout.
Votre projet doit avoir un init .py pour pouvoir être chargé en tant que module
sys._getframe(1)
la suggestion vient d' iciEnsuite, pour utiliser votre enregistreur dans tout autre fichier:
Avertissements:
import [your module]
cela ne fonctionnera pas:python -m [your module name].[your filename without .py]
__main__
, mais toute solution utilisant__name__
aura ce problème.la source