web-dev-qa-db-fra.com

Comment désactiver et réactiver la journalisation de la console en Python?

J'utilise le module logging de Python et je souhaite désactiver la journalisation de la console pendant un certain temps, mais cela ne fonctionne pas.

#!/usr/bin/python
import logging

logger = logging.getLogger() # this gets the root logger
# ... here I add my own handlers 
#logger.removeHandler(sys.stdout)
#logger.removeHandler(sys.stderr)

print logger.handlers 
# this will print [<logging.StreamHandler instance at ...>]
# but I may have other handlers there that I want to keep

logger.debug("bla bla")

Le code ci-dessus affiche le bla bla sur stdout et je ne sais pas comment désactiver en toute sécurité le gestionnaire de console. Comment puis-je être sûr de retirer temporairement la console StreamHandler et pas une autre?

120
sorin

J'ai trouvé une solution pour cela:

logger = logging.getLogger('my-logger')
logger.propagate = False
# now if you use logger it will not log to console.

Cela évitera que la journalisation soit envoyée au logger supérieur qui inclut la journalisation de la console.

168
sorin

J'utilise:

logger = logging.getLogger()
logger.disabled = True
... whatever you want ...
logger.disabled = False
75
infinito

Vous pouvez utiliser:

logging.basicConfig(level=your_level)

votre_niveau est l'un de ceux-ci:

      'debug': logging.DEBUG,
      'info': logging.INFO,
      'warning': logging.WARNING,
      'error': logging.ERROR,
      'critical': logging.CRITICAL

Ainsi, si vous définissez votre_niveau sur logging.CRITICAL, vous ne recevrez que les messages critiques envoyés par: 

logging.critical('This is a critical error message')

Régler votre_niveau sur logging.DEBUG affichera tous les niveaux de journalisation.

Pour plus de détails, jetez un œil à exemples de journalisation.

De la même manière, pour changer de niveau pour chaque gestionnaire, utilisez Handler.setLevel () function.

import logging
import logging.handlers

LOG_FILENAME = '/tmp/logging_rotatingfile_example.out'

# Set up a specific logger with our desired output level
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)

# Add the log message handler to the logger
handler = logging.handlers.RotatingFileHandler(
          LOG_FILENAME, maxBytes=20, backupCount=5)

handler.setLevel(logging.CRITICAL)

my_logger.addHandler(handler)
56
Vadikus

(question morte depuis longtemps, mais pour les futurs chercheurs)

Plus proche du code/de l’intention de l’affiche originale, cela fonctionne pour moi sous Python 2.6.

#!/usr/bin/python
import logging

logger = logging.getLogger() # this gets the root logger

lhStdout = logger.handlers[0]  # stdout is the only handler initially

# ... here I add my own handlers 
f = open("/tmp/debug","w")          # example handler
lh = logging.StreamHandler(f)
logger.addHandler(lh)

logger.removeHandler(lhStdout)

logger.debug("bla bla")

Le truc que je devais trouver était de supprimer le gestionnaire stdout après en ajoutant un nouveau; le code de l'enregistreur apparaît pour rajouter automatiquement le stdout si aucun gestionnaire n'est présent.

43
l82ky

Gestionnaire de contexte

import logging 
class DisableLogger():
    def __enter__(self):
       logging.disable(logging.CRITICAL)
    def __exit__(self, a, b, c):
       logging.disable(logging.NOTSET)

Exemple d'utilisation:

with DisableLogger():
    do_something()
35
pymen

Il y a de très bonnes réponses ici, mais apparemment la plus simple n’est pas trop prise en compte (seulement d’infinito).

root_logger = logging.getLogger()
root_logger.disabled = True

Cela désactive l’enregistreur racine, et donc tous les autres enregistreurs . Je n’ai pas vraiment testé, mais il devrait également être le plus rapide.

À partir du code de journalisation en python 2.7, je vois ceci

def handle(self, record):
    """
    Call the handlers for the specified record.

    This method is used for unpickled records received from a socket, as
    well as those created locally. Logger-level filtering is applied.
    """
    if (not self.disabled) and self.filter(record):
        self.callHandlers(record)

Ce qui signifie que lorsqu'il est désactivé, aucun gestionnaire n'est appelé et il devrait être plus efficace que de filtrer à une valeur très élevée ou de définir un gestionnaire sans opération, par exemple.

26
andrea_crotti

Pour désactiver complètement la journalisation:

logging.disable(sys.maxint) # Python 2

logging.disable(sys.maxsize) # Python 3

Pour activer la journalisation:

logging.disable(logging.NOTSET)

D’autres réponses proposent des solutions qui ne résolvent pas complètement le problème, telles que

logging.getLogger().disabled = True

et, pour certains n plus de 50 ans,

logging.disable(n)

Le problème avec la première solution est que cela ne fonctionne que pour le consignateur racine. Les autres enregistreurs créés avec, par exemple, logging.getLogger(__name__) ne sont pas désactivés par cette méthode.

La deuxième solution affecte tous les journaux. Mais il limite la sortie à des niveaux supérieurs à celui indiqué, de sorte que vous pouvez la remplacer en enregistrant avec un niveau supérieur à 50. 

Cela peut être empêché par

logging.disable(sys.maxint)

ce qui, autant que je sache, est le seul moyen de désactiver complètement la journalisation (après avoir examiné le fichier source ).

17
starfry

Pas besoin de dériver stdout. Voici une meilleure façon de le faire:

import logging
class MyLogHandler(logging.Handler):
    def emit(self, record):
        pass

logging.getLogger().addHandler(MyLogHandler())

Une façon encore plus simple est:

logging.getLogger().setLevel(100)
10
Ehsan Foroughi

Je ne connais pas très bien le module de journalisation, mais je l'utilise comme je ne souhaite généralement désactiver que les messages de débogage (ou d'informations). Vous pouvez utiliser Handler.setLevel() pour définir le niveau de consignation sur CRITICAL ou supérieur.

Vous pouvez également remplacer sys.stderr et sys.stdout par un fichier ouvert en écriture. Voir http://docs.python.org/library/sys.html#sys.stdout . Mais je ne recommanderais pas cela.

2
Krab

Vous pouvez aussi:

handlers = app.logger.handlers
# detach console handler
app.logger.handlers = []
# attach
app.logger.handlers = handlers
2
Italo Maia

sous-classe le gestionnaire que vous voulez pouvoir désactiver temporairement:

class ToggledHandler(logging.StreamHandler):
"""A handler one can turn on and off"""

def __init__(self, args, kwargs):
    super(ToggledHandler, self).__init__(*args, **kwargs)
    self.enabled = True  # enabled by default

def enable(self):
    """enables"""
    self.enabled = True

def disable(self):
    """disables"""
    self.enabled = False

def emit(self, record):
    """emits, if enabled"""
    if self.enabled:
        # this is taken from the super's emit, implement your own
        try:
            msg = self.format(record)
            stream = self.stream
            stream.write(msg)
            stream.write(self.terminator)
            self.flush()
        except Exception:
            self.handleError(record)

trouver le gestionnaire par son nom est assez facile:

_handler = [x for x in logging.getLogger('').handlers if x.name == your_handler_name]
if len(_handler) == 1:
    _handler = _handler[0]
else:
    raise Exception('Expected one handler but found {}'.format(len(_handler))

une fois trouvé:

_handler.disable()
doStuff()
_handler.enable()
0
jake77
import logging

log_file = 'test.log'
info_format = '%(asctime)s - %(levelname)s - %(message)s'
logging.config.dictConfig({
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'info_format': {
            'format': info_format
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'info_format'
        },
        'info_log_file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'level': 'INFO',
            'filename': log_file,
            'formatter': 'info_format'
        }
    },
    'loggers': {
        '': {
            'handlers': [
                'console',
                'info_log_file'
            ],
            'level': 'INFO'
        }
    }
})


class A:

    def __init__(self):
        logging.info('object created of class A')

        self.logger = logging.getLogger()
        self.console_handler = None

    def say(self, Word):
        logging.info('A object says: {}'.format(Word))

    def disable_console_log(self):
        if self.console_handler is not None:
            # Console log has already been disabled
            return

        for handler in self.logger.handlers:
            if type(handler) is logging.StreamHandler:
                self.console_handler = handler
                self.logger.removeHandler(handler)

    def enable_console_log(self):
        if self.console_handler is None:
            # Console log has already been enabled
            return

        self.logger.addHandler(self.console_handler)
        self.console_handler = None


if __== '__main__':
    a = A()
    a.say('111')
    a.disable_console_log()
    a.say('222')
    a.enable_console_log()
    a.say('333')

Sortie de la console:

2018-09-15 15:22:23,354 - INFO - object created of class A
2018-09-15 15:22:23,356 - INFO - A object says: 111
2018-09-15 15:22:23,358 - INFO - A object says: 333

contenu du fichier test.log:

2018-09-15 15:22:23,354 - INFO - object created of class A
2018-09-15 15:22:23,356 - INFO - A object says: 111
2018-09-15 15:22:23,357 - INFO - A object says: 222
2018-09-15 15:22:23,358 - INFO - A object says: 333
0
Shawn Hu