2013-02-13 12 views
6

Ho posto questa domanda per python 2 here, ma ho riscontrato nuovamente il problema quando la risposta non funzionava più per Python 3.2.3.Modifica del formato del messaggio di registrazione in base al livello di registrazione dei messaggi in Python3

Ecco il codice che funziona su Python 2.7.3:

import logging 

# Attempt to set up a Python3 logger than will print custom messages 
# based on each message's logging level. 
# The technique recommended for Python2 does not appear to work for 
# Python3 

class CustomConsoleFormatter(logging.Formatter): 
    """ 
    Modify the way DEBUG messages are displayed. 

    """ 
    def __init__(self, fmt="%(levelno)d: %(msg)s"): 
     logging.Formatter.__init__(self, fmt=fmt) 

    def format(self, record): 

     # Remember the original format 
     format_orig = self._fmt 

     if record.levelno == logging.DEBUG: 
      self._fmt = "DEBUG: %(msg)s" 

     # Call the original formatter to do the grunt work 
     result = logging.Formatter.format(self, record) 

     # Restore the original format 
     self._fmt = format_orig 

     return result 


# Set up a logger 
my_logger = logging.getLogger("my_custom_logger") 
my_logger.setLevel(logging.DEBUG) 

my_formatter = CustomConsoleFormatter() 

console_handler = logging.StreamHandler() 
console_handler.setFormatter(my_formatter) 

my_logger.addHandler(console_handler) 

my_logger.debug("This is a DEBUG-level message") 
my_logger.info("This is an INFO-level message") 

Una corsa con Python 2.7.3:

tcsh-16: python demo_python_2.7.3.py 
DEBUG: This is a DEBUG-level message 
20: This is an INFO-level message 


Per quanto posso dire, la conversione a Python3 richiede solo una leggera mod a CustomConsoleFormatter. init():

def __init__(self): 
    super().__init__(fmt="%(levelno)d: %(msg)s", datefmt=None, style='%') 

su Python 3.2.3:

tcsh-26: python3 demo_python_3.2.3.py 
10: This is a DEBUG-level message 
20: This is an INFO-level message 


Come si può vedere, il mio desiderio di sostituire il '10' con 'DEBUG' si sta contrastato.

Ho provato a scavare nel codice sorgente Python3 e sembra che l'istanza di PercentStyle stia clobberando self._fmt dopo che io, beh, lo cloberò da solo.

Le mie costolette di registrazione si fermano poco prima di essere in grado di aggirare questa ruga.

Qualcuno può consigliare un altro modo o forse sottolineare quello che sto trascurando?

risposta

7

Con un po 'di scavo, sono stato in grado di modificare la soluzione Python 2 per lavorare con Python 3. In Python2, era necessario sovrascrivere temporaneamente Formatter._fmt. In Python3, il supporto per più tipi di stringhe di formato richiede invece di sovrascrivere temporaneamente Formatter._style._fmt.

# Custom formatter 
class MyFormatter(logging.Formatter): 

    err_fmt = "ERROR: %(msg)s" 
    dbg_fmt = "DBG: %(module)s: %(lineno)d: %(msg)s" 
    info_fmt = "%(msg)s" 

    def __init__(self): 
     super().__init__(fmt="%(levelno)d: %(msg)s", datefmt=None, style='%') 

    def format(self, record): 

     # Save the original format configured by the user 
     # when the logger formatter was instantiated 
     format_orig = self._style._fmt 

     # Replace the original format with one customized by logging level 
     if record.levelno == logging.DEBUG: 
      self._style._fmt = MyFormatter.dbg_fmt 

     elif record.levelno == logging.INFO: 
      self._style._fmt = MyFormatter.info_fmt 

     elif record.levelno == logging.ERROR: 
      self._style._fmt = MyFormatter.err_fmt 

     # Call the original formatter class to do the grunt work 
     result = logging.Formatter.format(self, record) 

     # Restore the original format configured by the user 
     self._style._fmt = format_orig 

     return result 

Ed ecco l'esempio di Halloleo di come utilizzare quanto sopra nello script (dalla Python2 version of this question):

fmt = MyFormatter() 
hdlr = logging.StreamHandler(sys.stdout) 

hdlr.setFormatter(fmt) 
logging.root.addHandler(hdlr) 
logging.root.setLevel(DEBUG) 
2

cross-posting di another answer. Non funziona a causa della nuova implementazione (3.2+, 3.4 ad oggi) di logging.Formatter che ora si basa sugli stili di formattazione. Questo si basa sul formato di stile '{', ma può essere adattato. Potrebbe essere raffinato per essere più generale e consentire la selezione dello stile di formattazione e dei messaggi personalizzati come argomenti a __init__.

class SpecialFormatter(logging.Formatter): 
    FORMATS = {logging.DEBUG : logging._STYLES['{']("{module} DEBUG: {lineno}: {message}"), 
      logging.ERROR : logging._STYLES['{']("{module} ERROR: {message}"), 
      logging.INFO : logging._STYLES['{']("{module}: {message}"), 
      'DEFAULT' : logging._STYLES['{']("{module}: {message}")} 

    def format(self, record): 
     # Ugly. Should be better 
     self._style = self.FORMATS.get(record.levelno, self.FORMATS['DEFAULT']) 
     return logging.Formatter.format(self, record) 

hdlr = logging.StreamHandler(sys.stderr) 
hdlr.setFormatter(SpecialFormatter()) 
logging.root.addHandler(hdlr) 
logging.root.setLevel(logging.INFO) 
1

Sono in ritardo in ritardo per questa domanda, ma qui è la mia soluzione. Segue lo stile di sintassi originale di python 2. In generale ci sono tre nuove classi che dovresti usare a causa dell'aggiunta del supporto per gli stili. Quelli sono: PercentStyle, StrFormatStyle e StringTemplateStyle.

from logging import Formatter, PercentStyle, ERROR, WARNING, INFO, DEBUG 
class SrvLogFormat(Formatter): 
    def __init__(self): 
     super().__init__(fmt=env.fmt_log, datefmt=env.fmt_log_date) 

    def format(self, record): 
     original_style = self._style 

     if record.levelno == DEBUG: 
      self._style = PercentStyle(env.fmt_dflt) 
     if record.levelno == INFO: 
      self._style = PercentStyle(env.fmt_dflt) 
     if record.levelno == WARNING: 
      self._style = PercentStyle(env.fmt_dflt) 
     if record.levelno == ERROR: 
      self._style = PercentStyle(env.fmt_err) 

     result = Formatter.format(self, record) 
     self._style = original_style 
     return result 
Problemi correlati