2017-03-04 29 views
1

我正在学习在Python(3.6.0)中使用logging模块,并从Logging Cookbook的示例开始。但是,当代码从循环内运行时,日志消息会重复多次。这是为什么?在这种情况下有没有办法清空记录器?我试图玩logger.propagate,但没有成功。迭代中的空记录器

我的代码脚本testlog.py

#!/usr/bin/env python3 

import logging 

def main(): 
    t = (1,2,1,2,1) 

    logit('Log is fine here', '_logfile', logname='INFO', level='info') 

    for i,x in enumerate(t): 
     if x == 1: 
      logit('Warn at iter {}'.format(i), '_logfile', logname='INFO', level='info') 


def logit(message, logfile, logname='LOG', level='info'): 
    '''https://docs.python.org/3.6/howto/logging-cookbook.html#logging-to-multiple-destinations''' 

    logformat = '%(asctime)-30s %(levelname)-8s %(name)s\t%(message)s' 
    dateformat = '[ %Y-%m-%d %H:%M:%S ]' 
    # set up logging to file 
    logging.basicConfig(level=logging.DEBUG, 
         format=logformat, 
         datefmt=dateformat, 
         filename=logfile, 
         filemode='a') 

    # define a Handler which writes INFO messages or higher to the sys.stderr 
    console = logging.StreamHandler() 
    console.setLevel(logging.DEBUG) 
    # set a format which is simpler for console use 
    formatter = logging.Formatter(logformat, datefmt=dateformat) 
    # tell the handler to use this format 
    console.setFormatter(formatter) 
    # add the handler to the root logger 
    logging.getLogger('').addHandler(console) 
    # Now, we can log to the logger 
    logger = logging.getLogger(logname) 
    console.propagate = False 

    if level.lower() == 'debug': 
     logger.debug(message) 
    elif level.lower() == 'info': 
     logger.info(message) 
    elif level.lower().startswith('warn'): 
     logger.warning(message) 
    else: 
     logger.error(message) 

if __name__ == '__main__': 
    main() 

输出:

> ./testlog.py 
[ 2017-03-04 01:59:09 ]  INFO  INFO Log is fine here 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 0 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 0 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 2 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 2 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 2 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 4 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 4 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 4 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 4 

EDIT1:这个想法是登录到控制台和日志文件。 在日志文件中,消息不会重复。

[ 2017-03-04 01:59:09 ]  INFO  INFO Log is fine here 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 0 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 2 
[ 2017-03-04 01:59:09 ]  INFO  INFO Warn at iter 4 

回答

0

我让它工作在以下方式(大多数代码改编自here)。 首先需要创建一个函数来创建记录器并向其添加不同的处理程序。每个处理器可以有它自己的一套等级:

def set_logger(logfile, logname='LOG'): 

    logformat = '%(asctime)-30s %(levelname)-8s %(name)s\t%(message)s' 
    dateformat = '[ %Y-%m-%d %H:%M:%S ]' 

    # Setup Logging Object 
    logger = logging.getLogger(logname) 
    logger.setLevel(logging.DEBUG) 
    # Set log object to console 
    chandler = logging.StreamHandler() 
    chandler.setLevel(logging.DEBUG) 
    formatter = logging.Formatter(logformat, datefmt=dateformat) 
    chandler.setFormatter(formatter) 
    logger.addHandler(chandler) 

    # Set log object to file 
    fhandler = logging.FileHandler(filename=logfile, 
            mode='a') 
    fhandler.setLevel(logging.DEBUG) 
    formatter = logging.Formatter(logformat, datefmt=dateformat) 
    fhandler.setFormatter(formatter) 
    logger.addHandler(fhandler) 

    return logger 

然后记录仪可以被检索的main():

def main(): 

    logger=set_logger('_logfile') 

    t = (1,2,1,2,1) 

    # logit3('Log is fine here', '_logfile', logname='INFO', level='info') 
    logger.debug('Log is fine here') 

    for i,x in enumerate(t): 
     if x == 1: 
      # logit3('Warn at iter {}'.format(i), '_logfile', logname='INFO', level='info') 
      logger.debug('Warn at iter {}'.format(i)) 

在控制台输出:

[ 2017-03-04 11:21:02 ]  DEBUG LOG Log is fine here 
[ 2017-03-04 11:21:02 ]  DEBUG LOG Warn at iter 0 
[ 2017-03-04 11:21:02 ]  DEBUG LOG Warn at iter 2 
[ 2017-03-04 11:21:02 ]  DEBUG LOG Warn at iter 4 

在日志输出文件是:

[ 2017-03-04 11:21:02 ]  DEBUG LOG Log is fine here 
[ 2017-03-04 11:21:02 ]  DEBUG LOG Warn at iter 0 
[ 2017-03-04 11:21:02 ]  DEBUG LOG Warn at iter 2 
[ 2017-03-04 11:21:02 ]  DEBUG LOG Warn at iter 4 

不是当然,如果这是最合适的方法,但现在正如我所期望的那样工作。

0

这是特别是因为在logit下面一行: logging.getLogger('').addHandler(console)

每次调用logit时,您要添加另一个StreamHandler至根记录。你应该做一次记录器的所有配置。

+0

我明白了,但是在根记录器中添加一个新处理程序(本例中为控制台)的最佳方法是什么?显然,不可能在logging.basicConfig()中一起设置文件名和处理程序() – PedroA

+0

通常,您需要设置一次记录器。您可以创建另一个名为'setup_logging'的方法,它将文件作为参数并返回记录器。然后你的'logit'方法接收消息,记录器和关卡。因此,你的'main'方法会有一个'logger = setup_logging('my_log.log')',你对'logit'的调用看起来像'logit(logger,'my message','info')'(At这一点,但你可能不需要你的'logit'方法,可以直接调用'logger.info('my message')') – Stacktrace

+0

你可以给出具体的例子吗? – PedroA