2016-06-18 23 views
4

Ich habe zwei Handler mit verschiedenen Formatierern zu meinem Logger hinzugefügt. Die erste erfordert das Unterklassieren von logging.Formatter, um benutzerdefinierte Formatierungen durchzuführen. Der Standardformatierer wird für den zweiten Handler ausreichen.Subclassing logging.Formatter Änderungen Standardverhalten von logging.Formatter

Nehmen wir an, der erste Formatierer entfernt einfach Newline-Zeichen aus der Nachricht. Das folgende Skript zeigt, was wie seltsame Verhalten scheint:

import logging 

logger = logging.getLogger(__name__) 

class CustomFormatter(logging.Formatter): 
    def __init__(self, *args, **kwargs): 
     super().__init__(*args, **kwargs) 
    def format(self, record): 
     record.msg = record.msg.strip().replace('\n', ' ') 
     return super().format(record) 

h1 = logging.StreamHandler() 
formatter1 = CustomFormatter(fmt=None, datefmt=None) 
h1.setFormatter(formatter1) 
logger.addHandler(h1) 

h2 = logging.StreamHandler() 
formatter2 = logging.Formatter(fmt=None, datefmt=None) 
h2.setFormatter(formatter2) 
logger.addHandler(h2) 

logger.warning('string with\nmultiple lines') 

Dies gibt der folgende:

string with multiple lines 
string with multiple lines 

ich erwartet Sie stattdessen:

string with multiple lines 
string with 
multiple lines 

Der zweite Formatierer sollte das Verhalten von nicht implementieren CustomFormatter, aber es tut es. Wenn ich die Reihenfolge, in der die Handler zum Logger hinzugefügt werden, umkehren, geschieht dies nicht.

Wenn ich die Unterklasse nicht falsch verstehe, sollte das Verhalten der Basisklasse nicht durch Überschreiben einer Methode in einer Unterklasse geändert werden. Dies scheint kein Problem zu sein, wenn ich Methoden anderer Klassen als logging.Formatter außer Kraft setze.

Ist das ein Fehler im Logging-Modul, oder fehlt mir hier etwas?

+0

Interessanterweise habe ich 'logger.handlers [1] .formatter = None' und der Logger noch gedruckt glücklich zwei Zeilen. Aber 'logger.handlers [1] = None' hat die Dinge wie erwartet abgebrochen. – tdelaney

Antwort

2

Diese Linie war Ihr nach unten fallen:

record.msg = record.msg.strip().replace('\n', ' ') 

Sie neu zugewiesen, die geschrubbt String an die Platte, die an den Logger angebracht von den restlichen Handler/Formatierer verwendet wird. Kopieren Sie die Aufzeichnung und es funktioniert:

import logging 
from copy import copy 

logger = logging.getLogger(__name__) 

class CustomFormatter(logging.Formatter): 
    def __init__(self, *args, **kwargs): 
     super().__init__(*args, **kwargs) 
    def format(self, record): 
     record = copy(record) 
     record.msg = record.msg.strip().replace('\n', ' ') 
     return super().format(record) 

h1 = logging.StreamHandler() 
formatter1 = CustomFormatter(fmt=None, datefmt=None) 
h1.setFormatter(formatter1) 
logger.addHandler(h1) 

h2 = logging.StreamHandler() 
formatter2 = logging.Formatter(fmt=None, datefmt=None) 
h2.setFormatter(formatter2) 
logger.addHandler(h2) 

logger.warning('string with\nmultiple lines') 

Ausgänge

string with multiple lines 
string with 
multiple lines 
+0

Das macht Sinn - danke für den Hinweis auf meinen Fehltritt! –