Журнал Python - новый файл журнала каждой итерации цикла - PullRequest
0 голосов
/ 08 февраля 2019

Я хотел бы генерировать новый файл журнала на каждой итерации цикла в 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 голосов
/ 01 июня 2019

Это не обязательно лучший ответ, но сработал для моего случая, и я просто хотел разместить его здесь для будущих ссылок.Я создал функцию, которая выглядит следующим образом:

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)

Я надеюсь, что это полезно.

0 голосов
/ 08 февраля 2019

Возможно, это не лучшее решение, но оно будет создавать новый файл журнала для каждой итерации.Это делает добавление нового обработчика файлов в каждую итерацию.

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))
0 голосов
/ 08 февраля 2019

Вместо того, чтобы использовать logging напрямую, вам нужно использовать объекты регистратора.Внимательно изучите документы здесь .

Создайте новый объект регистратора в качестве первого оператора в цикле.Ниже приведено рабочее решение.

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)

Это записывает в отдельный файл журнала для каждой итерации.

0 голосов
/ 08 февраля 2019

Вот рабочая версия для этой проблемы.Я смог заставить его работать, только если у целей уже есть .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...')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...