Python日志记录-每个循环迭代时都有新的日志文件

时间:2019-02-08 11:22:40

标签: python logging

我想使用日志记录模块在Python循环的每次迭代中生成一个新的日志文件。我正在分析for循环中的数据,其中循环的每个迭代都包含有关新对象的信息。我想为每个对象生成一个日志文件。

我查看了日志记录模块的文档,并且能够按时间间隔或在日志文件填满时更改日志文件,但是我看不到如何迭代生成具有新名称的新日志文件。我提前知道循环中有多少个对象。

我想象的伪代码是:

import logging

for target in targets:
    logfile_name = f"{target}.log"
    logging.basicConfig(format='%(asctime)s - %(levelname)s : %(message)s',
                        datefmt='%Y-%m/%dT%H:%M:%S',
                        filename=logfile_name,
                        level=logging.DEBUG)


    # analyse target infomation
    logging.info('log target info...')

但是,日志记录信息总是附加到目标1的第一日志文件中。

是否有一种方法可以在每个循环开始时强制使用新的日志文件?

4 个答案:

答案 0 :(得分:1)

这可能不是最佳解决方案,但是它将为每次迭代创建新的日志文件。这是在每次迭代中添加一个新的文件处理程序。

import logging
targets = ["a", "b", "c"]
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

for target in targets:
    log_file = "{}.log".format(target)
    log_format = "|%(levelname)s| : [%(filename)s]--[%(funcName)s] : %(message)s"
    formatter = logging.Formatter(log_format)

    # create file handler and set the formatter
    file_handler = logging.FileHandler(log_file)
    file_handler.setFormatter(formatter)

    # add handler to the logger
    logger.addHandler(file_handler)

    # sample message
    logger.info("Log file: {}".format(target))

答案 1 :(得分:1)

您需要使用记录器对象,而不是直接使用logging。仔细阅读文档here

在循环中的第一个语句中创建一个新的记录器对象。下面是一个可行的解决方案。

import logging
import sys


def my_custom_logger(logger_name, level=logging.DEBUG):
    """
    Method to return a custom logger with the given name and level
    """
    logger = logging.getLogger(logger_name)
    logger.setLevel(level)
    format_string = ("%(asctime)s — %(name)s — %(levelname)s — %(funcName)s:"
                    "%(lineno)d — %(message)s")
    log_format = logging.Formatter(format_string)
    # Creating and adding the console handler
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(log_format)
    logger.addHandler(console_handler)
    # Creating and adding the file handler
    file_handler = logging.FileHandler(logger_name, mode='a')
    file_handler.setFormatter(log_format)
    logger.addHandler(file_handler)
    return logger


if __name__ == "__main__":
    for item in range(10):
        logger = my_custom_logger(f"Logger{item}")
        logger.debug(item)

这会为每次迭代写入不同的日志文件。

答案 2 :(得分:1)

这不一定是最佳答案,但适用于我的情况,只想将其放在此处以供将来参考。我创建了一个如下所示的函数:

def logger(filename, level=None, format=None):
    """A wrapper to the logging python module

    This module is useful for cases where we need to log in a for loop
    different files. It also will allow more flexibility later on how the
    logging format could evolve.

    Parameters
    ----------
    filename : str
        Name of logfile. 
    level : str, optional
        Level of logging messages, by default 'info'. Supported are: 'info'
        and 'debug'.
    format : str, optional
        Format of logging messages, by default '%(message)s'.

    Returns
    -------
    logger
        A logger object.
    """

    levels = {"info": logging.INFO, "debug": logging.DEBUG}

    if level is None:
        level = levels["info"]
    else:
        level = levels[level.lower()]

    if format is None:
        format = "%(message)s"

    # https://stackoverflow.com/a/12158233/1995261
    for handler in logging.root.handlers[:]:
        logging.root.removeHandler(handler)

    logger = logging.basicConfig(filename=filename, level=level, format=format)

    return logger

如您所见(您可能需要向下滚动上面的代码以查看return logger行),我正在使用logging.basicConfig()。程序包中包含所有用于记录内容的模块,这些文件的开头均包含以下内容:

import logging
import other stuff

logger = logging.getLogger()


class SomeClass(object):
    def some_method(self):
        logger.info("Whatever")
        .... stuff

做循环时,我这样称呼事情:

if __name__ == "__main__":
    for i in range(1, 11, 1):
        directory = "_{}".format(i)

        if not os.path.exists(directory):
            os.makedirs(directory)
        filename = directory + "/training.log"
        logger(filename=filename)

我希望这会有所帮助。

答案 3 :(得分:0)

这是此问题的有效版本。我只有在目标进入循环之前已经具有.log的情况下才能使它工作,因此您可能要在进入目标之前再添加一个目标,并使用.log扩展名覆盖所有目标

import logging

targets = ["a.log","b.log","c.log"]
for target in targets:

    log = logging.getLogger(target)
    formatter = logging.Formatter('%(asctime)s - %(levelname)s : %(message)s', datefmt='%Y-%m/%dT%H:%M:%S')
    fileHandler = logging.FileHandler(target, mode='a')
    fileHandler.setFormatter(formatter)
    streamHandler = logging.StreamHandler()
    streamHandler.setFormatter(formatter)
    log.addHandler(fileHandler)
    log.addHandler(streamHandler)

    log.info('log target info...')