web-dev-qa-db-fra.com

Supprimer la nouvelle ligne dans Python

J'essaie de remplacer un système de journalisation ad hoc par le module de journalisation de Python. J'utilise le système de journalisation pour produire des informations de progression pour une longue tâche sur une seule ligne afin que vous puissiez tail le journal ou le regarder dans une console. J'ai fait cela en ayant un indicateur sur ma fonction de journalisation qui supprime la nouvelle ligne pour ce message de journal et crée la ligne morceau par morceau.

Toute la journalisation est effectuée à partir d'un seul thread, il n'y a donc aucun problème de sérialisation.

Est-il possible de le faire avec le module de journalisation de Python? Est-ce que c'est une bonne idée?

33
Peter Graham

Commençons par votre dernière question: non, je ne pense pas que ce soit une bonne idée. OMI, cela nuit à la lisibilité du fichier journal à long terme.

Je suggère de rester avec le module logging et d'utiliser l'option '-f' sur votre commande 'tail' pour regarder la sortie de la console. Vous finirez probablement par utiliser le FileHandler . Notez que l'argument par défaut pour 'delay' est False, ce qui signifie que la sortie ne sera pas mise en mémoire tampon.

Si vous vraiment nécessaire pour supprimer les sauts de ligne, je recommanderais de créer votre propre gestionnaire.

8
jonEbird

Si vous le souhaitez, vous pouvez modifier le terminateur du gestionnaire de journalisation. J'utilise Python 3.4. Cela a été introduit dans Python 3.2 comme indiqué par Ninjakannon.

handler = logging.StreamHandler()
handler.terminator = ""

Lorsque le StreamHandler écrit, il écrit le terminateur en dernier.

34
justengel

La nouvelle ligne, \n, Est insérée dans la classe StreamHandler.

Si vous êtes vraiment déterminé à corriger ce comportement, alors voici un exemple de la façon dont j'ai résolu cela en patch de singe le emit(self, record) méthode à l'intérieur de la classe logging.StreamHandler.

Un patch monkey est un moyen d'étendre ou de modifier le code d'exécution de langages dynamiques sans altérer le code source d'origine. Ce processus a également été appelé poinçonnage de canard.

Voici l'implémentation personnalisée de emit() qui omet les sauts de ligne:

def customEmit(self, record):
    # Monkey patch Emit function to avoid new lines between records
    try:
        msg = self.format(record)
        if not hasattr(types, "UnicodeType"): #if no unicode support...
            self.stream.write(msg)
        else:
            try:
                if getattr(self.stream, 'encoding', None) is not None:
                    self.stream.write(msg.encode(self.stream.encoding))
                else:
                    self.stream.write(msg)
            except UnicodeError:
                self.stream.write(msg.encode("UTF-8"))
        self.flush()
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        self.handleError(record)

Ensuite, vous créez une classe de journalisation personnalisée (dans ce cas, sous-classe à partir de TimedRotatingFileHandler).

class SniffLogHandler(TimedRotatingFileHandler):
    def __init__(self, filename, when, interval, backupCount=0,
                 encoding=None, delay=0, utc=0):

        # Monkey patch 'emit' method
        setattr(StreamHandler, StreamHandler.emit.__name__, customEmit)

        TimedRotatingFileHandler.__init__(self, filename, when, interval,
                                          backupCount, encoding, delay, utc)

Certaines personnes pourraient soutenir que ce type de solution n'est pas Pythonic , ou autre. Il pourrait en être ainsi, alors soyez prudent.

Sachez également que cela corrigera globalement SteamHandler.emit(...), donc si vous utilisez plusieurs classes de journalisation, ce correctif affectera également les autres classes de journalisation!

Découvrez-les pour plus de lecture:

J'espère que cela pourra aider.

12
pjama

J'ai rencontré un besoin de journaliser une certaine section sur une seule ligne pendant que je parcourais un tuple, mais je voulais conserver l'enregistreur global.

J'ai d'abord collecté la sortie en une seule chaîne, puis je l'ai envoyée à l'enregistreur une fois que j'étais hors de la section. Exemple de concept

for fld in object._fields: 
  strX = (' {} --> {} ').format(fld, formattingFunction(getattr(obj,fld)))
debugLine += strX
logger.debug('{}'.format(debugLine))
0
Rembau Times