Existe-t-il un moyen de consigner Python à l'aide du module logging
et envoie automatiquement les éléments à stdout en plus dans le fichier journal où ils sont censés aller? Par exemple, je voudrais que tous les appels à logger.warning
, logger.critical
, logger.error
se dirigent vers leurs emplacements souhaités mais sont en outre toujours copiés vers stdout
. Ceci afin d'éviter la duplication de messages tels que:
mylogger.critical("something failed")
print "something failed"
Toutes les sorties de journalisation sont gérées par les gestionnaires. ajoutez simplement un logging.StreamHandler()
au logger racine.
Voici un exemple de configuration d'un gestionnaire de flux (en utilisant stdout
au lieu du paramètre par défaut stderr
) et en l'ajoutant au consignateur racine:
import logging
import sys
root = logging.getLogger()
root.setLevel(logging.DEBUG)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
root.addHandler(handler)
Le moyen le plus simple de se connecter à stdout:
import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
C'est possible en utilisant plusieurs gestionnaires.
import logging
import auxiliary_module
# create logger with 'spam_application'
log = logging.getLogger('spam_application')
log.setLevel(logging.DEBUG)
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
log.addHandler(fh)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
ch.setFormatter(formatter)
log.addHandler(ch)
log.info('creating an instance of auxiliary_module.Auxiliary')
a = auxiliary_module.Auxiliary()
log.info('created an instance of auxiliary_module.Auxiliary')
log.info('calling auxiliary_module.Auxiliary.do_something')
a.do_something()
log.info('finished auxiliary_module.Auxiliary.do_something')
log.info('calling auxiliary_module.some_function()')
auxiliary_module.some_function()
log.info('done with auxiliary_module.some_function()')
# remember to close the handlers
for handler in log.handlers:
handler.close()
log.removeFilter(handler)
Veuillez consulter: https://docs.python.org/2/howto/logging-cookbook.html
Vous pouvez créer deux gestionnaires pour fichier et stdout, puis créer un journal avec l'argument handlers
to basicConfig
. Cela pourrait être utile si vous avez le même log_level et le même format de sortie pour les deux gestionnaires:
import logging
import sys
file_handler = logging.FileHandler(filename='tmp.log')
stdout_handler = logging.StreamHandler(sys.stdout)
handlers = [file_handler, stdout_handler]
logging.basicConfig(
level=logging.DEBUG,
format='[%(asctime)s] {%(filename)s:%(lineno)d} %(levelname)s - %(message)s',
handlers=handlers
)
logger = logging.getLogger('LOGGER_NAME')
Le moyen le plus simple de se connecter au fichier et à stderr:
import logging
logging.basicConfig(filename="logfile.txt")
stderrLogger=logging.StreamHandler()
stderrLogger.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
logging.getLogger().addHandler(stderrLogger)
Comme personne n’a partagé une doublure soignée, je partagerai la mienne:
logging.basicConfig(filename='logs.log', level=logging.DEBUG, format="%(asctime)s:%(levelname)s: %(message)s")
logging.getLogger().addHandler(logging.StreamHandler())
Voici une solution basée sur la puissante mais mal documentée méthode logging.config.dictConfig
] . Au lieu d'envoyer chaque message de journal à stdout, il envoie des messages avec le niveau de journalisation ERROR
et les versions supérieures à stderr
et tout le reste à stdout
. Cela peut être utile si d'autres parties du système écoutent stderr
ou stdout
.
import logging
import logging.config
import sys
class _ExcludeErrorsFilter(logging.Filter):
def filter(self, record):
"""Filters out log messages with log level ERROR (numeric value: 40) or higher."""
return record.levelno < 40
config = {
'version': 1,
'filters': {
'exclude_errors': {
'()': _ExcludeErrorsFilter
}
},
'formatters': {
# Modify log message format here or replace with your custom formatter class
'my_formatter': {
'format': '(%(process)d) %(asctime)s %(name)s (line %(lineno)s) | %(levelname)s %(message)s'
}
},
'handlers': {
'console_stderr': {
# Directs log messages with log level ERROR or higher to stderr
'class': 'logging.StreamHandler',
'level': 'ERROR',
'formatter': 'my_formatter',
'stream': sys.stderr
},
'console_stdout': {
# Directs log messages with log level lower than ERROR to stdout
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'my_formatter',
'filters': ['exclude_errors'],
'stream': sys.stdout
},
'file': {
# Directs all log messages to a file
'class': 'logging.FileHandler',
'level': 'DEBUG',
'formatter': 'my_formatter',
'filename': 'my.log',
'encoding': 'utf8'
}
},
'root': {
# In general, this should be kept at 'NOTSET' to ensure it does
# not interfere with the log levels set for each handler
'level': 'NOTSET',
'handlers': ['console_stderr', 'console_stdout', 'file']
},
}
logging.config.dictConfig(config)
Voici un exemple extrêmement simple:
import logging
l = logging.getLogger("test")
# Add a file logger
f = logging.FileHandler("test.log")
l.addHandler(f)
# Add a stream logger
s = logging.StreamHandler()
l.addHandler(s)
# Send a test message to both -- critical will always log
l.critical("test msg")
La sortie affichera "message texte" sur stdout et également dans le fichier.
Jetez un coup d'œil au module logur .
from loguru import logger
logger.debug("That's it, beautiful and simple logging!")