web-dev-qa-db-fra.com

configuration du consignateur pour enregistrer dans un fichier et imprimer sur une sortie standard

J'utilise le module de journalisation de Python pour consigner des chaînes de débogage dans un fichier qui fonctionne plutôt bien. De plus, j'aimerais utiliser ce module pour imprimer également les chaînes sur la sortie standard. Comment puis-je faire cela? Afin de connecter mes chaînes dans un fichier, j'utilise le code suivant:

import logging
import logging.handlers
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(
    LOGFILE, maxBytes=(1048576*5), backupCount=7
)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)

puis appelez une fonction logger comme

logger.debug("I am written to the file")

Merci pour l'aide ici!

291
stdcerr

Il suffit d’obtenir une poignée pour le logger racine et d’ajouter le StreamHandler. La StreamHandler écrit dans stderr. Vous ne savez pas vraiment si vous avez vraiment besoin de stdout sur stderr, mais c’est ce que j’utilise lorsque j’installe le consignateur Python et que j’ajoute également le FileHandler. Ensuite, tous mes journaux vont aux deux endroits (ce qui ressemble à ce que vous voulez).

import logging
logging.getLogger().addHandler(logging.StreamHandler())

Si vous voulez générer stdout au lieu de stderr, il vous suffit de l'indiquer dans le constructeur StreamHandler.

import sys
# ...
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))

Vous pouvez également ajouter un Formatter afin que toutes vos lignes de journal aient un en-tête commun.

c'est à dire:

import logging
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s")
rootLogger = logging.getLogger()

fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)

consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)

Imprime au format de:

2012-12-05 16:58:26,618 [MainThread  ] [INFO ]  my message
380
Waterboy

logging.basicConfig() peut prendre un argument de mot clé handlers depuis Python 3.3, ce qui simplifie beaucoup la configuration de la journalisation, en particulier lors de la configuration de plusieurs gestionnaires avec le même formateur:

handlers - Si spécifié, il doit s'agir d'une liste de gestionnaires déjà créés à ajouter à l'enregistreur racine. Tous les gestionnaires qui ne possèdent pas déjà un ensemble de formateurs se verront attribuer le formateur par défaut créé dans cette fonction.

Le code d'exemple assez long et détaillé de la réponse acceptée devient alors simplement ceci:

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s",
    handlers=[
        logging.FileHandler("{0}/{1}.log".format(logPath, fileName)),
        logging.StreamHandler()
    ])

(Ou avec import sys + StreamHandler(sys.stdout) selon les exigences de la question d'origine.)

Pour obtenir l'enregistreur, utilisez

logger = logging.getLogger()

Plus tard dans votre script, utilisez logger.info() pour générer des messages de journalisation utiles.

170
Yirkha

Ajouter un StreamHandler sans argument va dans stderr au lieu de stdout. Si un autre processus a une dépendance sur le vidage de stdout (c'est-à-dire lors de l'écriture d'un plug-in NRPE), assurez-vous de spécifier explicitement stdout, sinon vous pourriez rencontrer des problèmes inattendus.

Voici un exemple rapide en réutilisant les valeurs supposées et LOGFILE de la question:

import logging
from logging.handlers import RotatingFileHandler
from logging import handlers
import sys

log = logging.getLogger('')
log.setLevel(logging.DEBUG)
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")

ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)

fh = handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
fh.setFormatter(format)
log.addHandler(fh)
63
Hazok

Lancez basicConfig avec stream=sys.stdout comme argument avant de configurer d’autres gestionnaires ou de consigner des messages, ou ajoutez manuellement un StreamHandler qui envoie les messages à stdout dans le logger racine (ou tout autre enregistreur que vous voulez, d'ailleurs).

19
Silas Ray

Après avoir utilisé le code de Waterboy à plusieurs reprises dans plusieurs packages Python, je l'ai finalement jeté dans un minuscule package autonome Python, que vous pouvez trouver ici:

https://github.com/acschaefer/duallog

Le code est bien documenté et facile à utiliser. Il suffit de télécharger le fichier .py et de l’inclure dans votre projet ou d’installer le package complet via pip install duallog.

2
Lexxer