如何使用日志模块避免重复输出

How to avoid duplicate outputs using logging module

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

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()

感谢 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 = []

就这样做:

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