防止python日志库的双输出

时间:2018-05-18 15:17:37

标签: python python-3.x logging

右。我正在运行一个相当复杂(对我而言)的基于对象的模型,而我正在寻求按顺序获取输出。以前我只是使用print()将输出转储到控制台,如果我想打开和关闭不同的功能,则将if函数附加到它们。虽然这在基本代码上运行良好,但我对这个项目有点不了解(这比我之前尝试过的事情要大一个数量级)。据我所知,python日志库允许我更整齐地执行此操作并输出到日志文件等。

目前,代码在运行时运行此功能,它以我想要的方式设置所有内容(我认为)。我已经在模型中进行了设置,因为我将进行整体运行,并且我想每次重新命名日志文件以进行新的运行。

def set_logger(file_name):
    '''sets up output via loggers and a output file.'''
    output = ('%(asctime)-20s %(filename)-15s %(funcName)-15s %(levelname)-8s %(message)s')
    logging.basicConfig(level=logging.DEBUG,
                        format=output,
                        filename=file_name,
                        filemode='w')
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    formatter = logging.Formatter('%(message)s')
    console.setFormatter(formatter)
    logging.getLogger('').addHandler(console)
    return

此代码输出从DEBUG级别到日志文件的所有内容,同时显示INFO以及控制台。

我的问题是,当执行完成时,记录器似乎保持活动状态,所以我第一次运行时最终会出现双行控制台输出(虽然不在日志文件中),下一次是三行,所以on ...我认为这与这一行有关:logging.getLogger('').addHandler(console),因为我每次运行代码时都会添加一个新的处理程序。

有没有确定的方法来避免这种情况?我希望能够像往常一样运行代码并让它检测是否存在console的现有实例,如果存在则只是不复制它,但文档很难理解一个,它让我难过。

有什么建议吗?谢谢!

2 个答案:

答案 0 :(得分:1)

只需检查您的RootLogger(logging.getLogger(''))是否具有处理程序:

def set_logger(file_name):
    '''sets up output via loggers and a output file.'''
    output = ('%(asctime)-20s %(filename)-15s %(funcName)-15s %(levelname)-8s %(message)s')
    logging.basicConfig(level=logging.DEBUG,
                        format=output,
                        filename=file_name,
                        filemode='w')
    root_logger = logging.getLogger('')
    if len(root_logger.handlers) > 0: # verifies if it has already a handler
        console = logging.StreamHandler()
        console.setLevel(logging.INFO)
        formatter = logging.Formatter('%(message)s')
        console.setFormatter(formatter)
        root_logger.addHandler(console)

但是,如果将来您有多个处理程序,并且想要检查记录器中是否有一个特定处理程序,则可以将处理程序命名为更精确:

def set_logger(file_name):
    '''sets up output via loggers and a output file.'''
    output = ('%(asctime)-20s %(filename)-15s %(funcName)-15s %(levelname)-8s %(message)s')
    logging.basicConfig(level=logging.DEBUG,
                        format=output,
                        filename=file_name,
                        filemode='w')
    root_logger = logging.getLogger('')
    # Verify if there is already a handler named "console"
    if any((handler.name == "console" for handler in root_logger.handlers)):
        console = logging.StreamHandler()
        console.name = "console"
        console.setLevel(logging.INFO)
        formatter = logging.Formatter('%(message)s')
        console.setFormatter(formatter)
    root_logger.addHandler(console)

答案 1 :(得分:0)

好的,我一发布这个问题就遇到了this answer,虽然这种做法很快而且很脏,却可以做到这一点。在开头添加此代码,擦除处理程序列表,我们每次只添加一个新代码。不如eqperes那么优雅,但它确实起到了作用......

root_logger.handlers = []