2013-12-20 6 views
9

Lassen Sie uns das vereinfachen. Mein Ziel ist die Farbausgabe im Terminal unter Verwendung des logging Moduls in Python. Ich möchte, dass info ein grünes Präfix hat, Warnungen ein gelbes Präfix und Fehler ein rotes Präfix haben. Um es einfach die *** als Präfix dhFarbprotokollierung mit Protokollierungsmodul in Python

*** log text 
*** another message with another prefix color 

verwenden lassen, was ich bisher getan haben

# declaration of function (global scope) 
log = None 
warn = None 
error = None 
def build_log_funcs(): 
    # why I initialize it inside the function ? 
    # because script doesnt have to know about logging method 
    # the function just provide log functions 
    logger = logging.getLogger(__name__) 
    logger.setLevel(logging.INFO) 

    sh = logging.StreamHandler() 
    # LOG_FORMAT just global variable with pattern including %(levelmarks)s 
    # it will be replaced with ** with proper color 
    formatter = logging.Formatter(LOG_FORMAT) 
    sh.setFormatter(formatter) 
    logger.addHandler(sh) 

    def make_log_func(func, color, is_exit = False): 
     color_string = "\x1b[{};1m***\x1b[0m".format(color) 
     def newfunc(*args, **kwargs): 
      func(*args, extra={'levelmarks':color_string}, **kwargs) 
      if is_exit: 
       sys.exit(-1) 

     return newfunc 
    # 32, 33, 31 are color codes 
    log = make_log_func(logger.info, 32) 
    warn = make_log_func(logger.warning, 33) 
    error = make_log_func(logger.error, 31, is_exit = True) 

    return log, warn, error 

Und verwenden Sie es als

log, warn, error = build_log_funcs() 

Es funktioniert, aber was ich nicht wie: (von kleinen zu großen Problemen)

  1. Ich verberge die Fähigkeiten von logging Modul. Zum Beispiel Aktivieren/Deaktivieren von Debug-Nachrichten
  2. Ich sollte globale Deklaration von Funktionen vor ihrer Initialisierung verwenden, weil ich eine Funktion vor seiner Deklaration nicht aufrufen kann.
  3. Es ist zu schwierig, den Code zu lesen und zu pflegen. Ich glaube, dass alles so einfach wie möglich sein sollte.

Warum mache ich nicht einfach Log, warn, einfache Funktion? Ich weiß es nicht. logging ist das sehr umfassende Modul, so dass ich in Zukunft seine Funktionen brauchen werde.

Meine Frage ist, wie Sie dieses Problem lösen würden? Vielleicht gibt es einen einfachen offensichtlichen Weg, den ich nicht kenne.

+1

Es wird netter sein, dies mit Dekorateuren zu tun. Sehen Sie diese ausgezeichnete Antwort [hier] (http://stackoverflow.com/a/6196103/674039) – wim

+2

Haben Sie [diese] (http://stackoverflow.com/a/1336640/142637) gesehen? – sloth

Antwort

3

Danke Dominic Kexel für this Link. Ich habe das gesehen, aber nicht auf die Antwort geachtet. Der folgende Code ist mehr oder weniger geeignet für mich

def setup_logger(logger): 
    logger.setLevel(logging.DEBUG) 

    sh = logging.StreamHandler() 
    formatter = logging.Formatter(LOG_FORMAT) 
    sh.setFormatter(formatter) 

    def decorate_emit(fn): 
    # add methods we need to the class 
     def new(*args): 
      levelno = args[0].levelno 
      if(levelno >= logging.CRITICAL): 
       color = '\x1b[31;1m' 
      elif(levelno >= logging.ERROR): 
       color = '\x1b[31;1m' 
      elif(levelno >= logging.WARNING): 
       color = '\x1b[33;1m' 
      elif(levelno >= logging.INFO): 
       color = '\x1b[32;1m' 
      elif(levelno >= logging.DEBUG): 
       color = '\x1b[35;1m' 
      else: 
       color = '\x1b[0m' 
      # add colored *** in the beginning of the message 
      args[0].msg = "{0}***\x1b[0m {1}".format(color, args[0].msg) 

      # new feature i like: bolder each args of message 
      args[0].args = tuple('\x1b[1m' + arg + '\x1b[0m' for arg in args[0].args) 
      return fn(*args) 
     return new 
    sh.emit = decorate_emit(sh.emit) 
    logger.addHandler(sh) 

Es gibt einen Fehler in dieser: Ich kann nicht die Position des *** im Muster steuern kann, aber wie gesagt, es ist geeignet.