web-dev-qa-db-fra.com

Comment insérer une nouvelle ligne dans la journalisation python?

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.warning('\n new hello')

11h15:01 INFO bonjour
11:16:49 AVERTISSEMENT
nouveau salut

Comme le journal est encombré, je souhaite insérer explicitement une nouvelle ligne before asctime et levelname Est-ce possible sans modifier format?

J'ai regardé dans le module logging et googlé un peu et je ne pouvais pas trouver un moyen viable.

21
est

J'ai deux solutions, la première est très facile, mais la sortie n'est pas très propre. La seconde méthode produira exactement le résultat souhaité, mais elle est un peu plus complexe.

Méthode 1

Pour produire une ligne vide, il suffit de consigner une chaîne vide avec une nouvelle ligne:

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.info('\n')
logging.warning('new hello')

La sortie aura une ligne d'information vide, ce qui n'est pas très propre:

16:07:26 INFO bonjour
16:07:26 INFO 

16:07:26 AVERTISSEMENT nouveau salut

Méthode 2

Dans cette méthode, j'ai créé deux gestionnaires différents. Le console_handler que j'utilise le plus souvent. Lorsque j'ai besoin d'une nouvelle ligne, je passe à un second gestionnaire, blank_handler.

import logging
import types

def log_newline(self, how_many_lines=1):
    # Switch handler, output a blank line
    self.removeHandler(self.console_handler)
    self.addHandler(self.blank_handler)
    for i in range(how_many_lines):
        self.info('')

    # Switch back
    self.removeHandler(self.blank_handler)
    self.addHandler(self.console_handler)

def create_logger():
    # Create a handler
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)
    console_handler.setFormatter(logging.Formatter(fmt="%(name)s %(levelname)-8s: %(message)s"))

    # Create a "blank line" handler
    blank_handler = logging.StreamHandler()
    blank_handler.setLevel(logging.DEBUG)
    blank_handler.setFormatter(logging.Formatter(fmt=''))

    # Create a logger, with the previously-defined handler
    logger = logging.getLogger('logging_test')
    logger.setLevel(logging.DEBUG)
    logger.addHandler(console_handler)

    # Save some data and add a method to logger object
    logger.console_handler = console_handler
    logger.blank_handler = blank_handler
    logger.newline = types.MethodType(log_newline, logger)

    return logger

if __== '__main__':
    logger = create_logger()
    logger.info('Start reading database')
    logger.info('Updating records ...')
    logger.newline()
    logger.info('Finish updating records')

La sortie est ce que vous voulez voir:

logging_test INFO    : Start reading database
logging_test INFO    : Updating records ...

logging_test INFO    : Finish updating records

Discussion

  • Si vous pouvez supporter un résultat moins que parfait, la méthode 1 est la voie à suivre. Il a l'avantage d'être simple, avec moins d'effort.
  • La deuxième méthode fait le travail correctement, mais elle est un peu compliquée. Il crée deux gestionnaires différents et les commute pour atteindre votre objectif.
  • Un autre inconvénient de la méthode 2 est que vous devez modifier votre code en recherchant logging et en les remplaçant par logger. Vous devez veiller à ne remplacer que les parties pertinentes et laisser le texte logging.DEBUG intact.
23
Hai Vu

Ne pourriez-vous pas ajouter la nouvelle ligne après le premier bonjour? c'est à dire.

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello\n')
logging.info('new hello')

Qui va sortir

2014-08-06 11:37:24,061 INFO    : hello

2014-08-06 11:37:24,061 INFO    : new hello
5
Spatial K

Utilisez une variable Formatter personnalisée qui utilise des chaînes de format différentes à des moments différents. Vous ne pouvez pas faire cela en utilisant basicConfig() - vous devrez utiliser d'autres parties de l'API logging.

class MyFormatter(logging.Formatter):
    def format(self, record):
        # set self._fmt to value with or without newline,
        # as per your decision criteria
        # self._fmt = ...
        return super(MyFormatter, self).format(record)

Ou, vous pouvez appeler la méthode super, puis modifier la chaîne pour insérer une nouvelle ligne avant de la renvoyer (au cas où cela dépend de la longueur de la ligne, par exemple).

3
Vinay Sajip

Le moyen le plus simple d'insérer des nouvelles lignes que j'ai compris:

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s\n\r%(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.info('new hello')

11:50:32 INFO
Bonjour
11:50:32 INFO
nouveau salut

1
Alex_Alex

Comme alternative à Hai Vu Méthode 2 , vous pouvez également réinitialiser la variable Formatter du gestionnaire chaque fois que vous souhaitez enregistrer une nouvelle ligne:

import logging
import types

def log_newline(self, how_many_lines=1):
    # Switch formatter, output a blank line
    self.handler.setFormatter(self.blank_formatter)

    for i in range(how_many_lines):
        self.info('')

    # Switch back
    self.handler.setFormatter(self.formatter)


def create_logger():
    # Create a handler
    handler = logging.StreamHandler()
    handler.setLevel(logging.DEBUG)
    formatter = logging.Formatter(fmt="%(name)s %(levelname)-8s: %(message)s")        
    blank_formatter = logging.Formatter(fmt="")
    handler.setFormatter(formatter)


    # Create a logger, with the previously-defined handler
    logger = logging.getLogger('logging_test')
    logger.setLevel(logging.DEBUG)
    logger.addHandler(handler)

    # Save some data and add a method to logger object
    logger.handler = handler
    logger.formatter = formatter
    logger.blank_formatter = blank_formatter
    logger.newline = types.MethodType(log_newline, logger)

    return logger

if __== '__main__':
    logger = create_logger()
    logger.info('Start reading database')
    logger.info('Updating records ...')
    logger.newline()
    logger.info('Finish updating records')

Sortie

logging_test INFO    : Start reading database  
logging_test INFO    : Updating records ...

logging_test INFO    : Finish updating records

L'avantage de ceci est que vous avez un seul gestionnaire. Par exemple, vous pouvez définir un attribut FileHandler 'mode- à écrire, si vous souhaitez nettoyer votre fichier journal à chaque nouvelle exécution de votre programme.

1
paulkernstock

Pour donner suite à la réponse utile de Vinay Salip (ci-dessous), je l’ai fait de cette façon (j’utilise la convention python3 superclass, mais super(MyFormatter, self) fonctionne tout aussi bien) ...

class MyFormatter(logging.Formatter):
    def format(self, record):
        return super().format(record).replace(r'\n', '\n')

Ensuite, je peux intégrer les nouvelles lignes comme suit:

logging.info('Message\\n\\n\\n\\nOther stuff')

ou

logging.info(r'Message\n\n\n\nOther stuff')
0
HippoMan

Si vous souhaitez simplement générer du code de débogage en développement, vous ne voudrez peut-être pas perdre de temps à cela. La solution de 5 secondes est la suivante:

str = "\n\n\n"
log.getLogger().debug(str)

où l'enregistreur est l'enregistreur python standard

0
Jake