【问题标题】:How to avoid duplicate outputs using logging module如何使用日志记录模块避免重复输出
【发布时间】:2015-04-05 17:46:12
【问题描述】:

我正在使用日志记录模块将脚本中的打印语句输出到控制台和日志文件。但是,每次我运行脚本时,输出似乎都会附加到控制台和日志中打印的内容,而不是覆盖那里的内容。例如,第一次运行脚本时,我会在控制台和日志文件中得到以下输出:

This print statement is going to both the console and the log
The year is: 2015

我第二次运行脚本时,我在控制台中得到了这个:

This print statement is going to both the console and the log
This print statement is going to both the console and the log
The year is: 2015
The year is: 2015

第三次:

This print statement is going to both the console and the log
This print statement is going to both the console and the log
This print statement is going to both the console and the log
The year is: 2015
The year is: 2015
The year is: 2015

等等..并且日志文件不断追加,所以我最终得到:

This print statement is going to both the console and the log
The year is: 2015
This print statement is going to both the console and the log
This print statement is going to both the console and the log
The year is: 2015
The year is: 2015
This print statement is going to both the console and the log
This print statement is going to both the console and the log
This print statement is going to both the console and the log
The year is: 2015
The year is: 2015
The year is: 2015

我想要的是日志文件和控制台都只给我以下内容,无论我重新运行脚本多少次:

This print statement is going to both the console and the log
The year is: 2015

注意:我目前能够得到我想要的唯一方法是在脚本运行之间关闭 Python,但这不是一个实际的解决方案。

我已经尝试过使用 flush() 并尝试过这样做:

logger = logging.basicConfig(filemode='w', level=logging.DEBUG)

但我无法让它与我的代码一起使用。有人可以帮忙吗?这是我的代码:

import inspect
import logging
import datetime

def getDate():
    now = datetime.datetime.now()
    m = now.month
    d = now.day
    y = str(now.year)
    if m < 10:
        m = "0"+str(m)
    else:
        m = str(m)
    if d < 10:
        d = "0"+str(d)
    else:
        d = str(d)
    y = y[2:]
    formatted_date = m+d+y
    return formatted_date

def function_logger(file_level, console_level = None):
    function_name = inspect.stack()[1][3]
    logger = logging.getLogger(function_name)
    logger.setLevel(logging.DEBUG) #By default, logs all messages

    if console_level != None:
        ch = logging.StreamHandler() #StreamHandler logs to console
        ch.setLevel(console_level)
        ch_format = logging.Formatter('%(message)s')
        ch.setFormatter(ch_format)
        logger.addHandler(ch)

    log_name = 'Test_log' + getDate() + '.log'
    fh = logging.FileHandler(log_name.format(function_name))
    fh.setLevel(file_level)
    fh_format = logging.Formatter('%(message)s')
    fh.setFormatter(fh_format)
    logger.addHandler(fh)
    return logger

def f1():
    global logger
    year = '2015'
    logger.info("The year is: %s" % (year))

def main():

    global logger
    logger = function_logger(logging.INFO, logging.INFO)
    logger.info('This print statement is going to both the console and the log')
    f1()
    logging.shutdown()

if __name__ == '__main__':
    main()

【问题讨论】:

  • 您看到这一点是因为每个处理程序都会发出一次记录,如果您多次运行脚本,您将在每个addHandler() 调用中注册一个新的处理程序。跟踪您的日志处理程序并在try..finally 中再次删除它们,或者在添加它们之前检查是否已经为您要添加的类型注册了一个。
  • (在每次运行期间打印 logger.handlers 以查看发生了什么)
  • 谢谢。将我的两个 addHandlers 都放在 if not logger.handlers: 下解决了重复条目的问题。但是,还有一个仅与日志文件有关的次要问题,即日志仍然被附加到而不是被覆盖。我该如何解决这个剩余的日志问题?
  • 如果您查看FileHandler 的构造函数,它的mode 默认为'a'(附加)。所以使用FileHandler(log_name.format(function_name), mode='w') 覆盖现有文件而不是追加(mode 的语义与open() 相同)。

标签: python logging


【解决方案1】:

感谢 Lucas Graf,这是我修复代码以完全按照我想要的方式进行的:

def function_logger(file_level, console_level = None):
    function_name = inspect.stack()[1][3]
    logger = logging.getLogger(function_name)
    logger.setLevel(logging.DEBUG) #By default, logs all messages
    log_name = 'Test_log_' + getDate() + '.log'

    if not logger.handlers:
        if console_level != None:
            ch = logging.StreamHandler() #StreamHandler logs to console
            ch.setLevel(console_level)
            ch_format = logging.Formatter('%(message)s')
            ch.setFormatter(ch_format)
            logger.addHandler(ch)

        fh = logging.FileHandler(log_name.format(function_name), mode='w')
        fh.setLevel(file_level)
        fh_format = logging.Formatter('%(message)s')
        fh.setFormatter(fh_format)
        logger.addHandler(fh)

    return logger

关于此修复需要注意三点:

1:我在测试条件下移动了两个addHandlers:

if not logger.handlers:

2:我在 Filhandler 中添加了 mode='w':

fh = logging.FileHandler(log_name.format(function_name), mode='w')

3:我清除了 main() 底部的处理程序:

logger.handlers = []

【讨论】:

    【解决方案2】:

    就这样做吧:

    def LOG_insere(file, format, text, level):
        infoLog = logging.FileHandler(file)
        infoLog.setFormatter(format)
        logger = logging.getLogger(file)
        logger.setLevel(level)
        
        if not logger.handlers:
            logger.addHandler(infoLog)
            if (level == logging.INFO):
                logger.info(text)
            if (level == logging.ERROR):
                logger.error(text)
            if (level == logging.WARNING):
                logger.warning(text)
        
        infoLog.close()
        logger.removeHandler(infoLog)
        
        return
    

    【讨论】:

      猜你喜欢
      • 2020-11-03
      • 2011-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-09
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多