2013-12-20 80 views
9

讓我們來簡化它。我的目標是在Python中使用logging模塊在終端中進行顏色輸出。我想要info有一個綠色的前綴,警告有一個黃色的前綴,錯誤有一個紅色的前綴。爲簡單起見,讓我們使用***作爲前綴,即在Python中使用記錄模塊進行顏色記錄

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

我做了什麼至今

# 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 

並以此

log, warn, error = build_log_funcs() 

它的工作原理,但我不(從小到大的問題)

  1. 我隱藏了logging模塊的功能。例如啓用/禁用調試消息
  2. 我應該在初始化之前使用函數的全局聲明,因爲在聲明之前我不能調用函數。
  3. 閱讀和維護代碼太困難了。我相信一切都應該儘可能簡單。

爲什麼我不做簡單的日誌,警告,簡單的功能?我不知道。 logging是非常全面的模塊,因此未來我將需要它的功能。

我的問題是你將如何解決這個問題?可能有一個簡單明顯的方式,我不知道。

+1

用裝飾器做這件事會更好。看到這個優秀的答案[這裏](http://stackoverflow.com/a/6196103/674039) – wim

+2

你見過[this](http://stackoverflow.com/a/1336640/142637)? – sloth

回答

3

感謝Dominic Kexel爲this的鏈接。我看到了這一點,但沒有注意答案。 下面的代碼是我

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) 

有這一個缺陷或多或少地適合我無法控制的格局***的位置,但正如我說這是合適的。