Как использовать несколько форматов для одного регистратора - PullRequest
0 голосов
/ 07 ноября 2019

У меня есть модуль, который выводит данные на консоль и в файл журнала. Я бы хотел, чтобы вывод консоли имел простой формат '%(message)s', но в файле журнала я хотел бы добавить метку времени '%(asctime)s - %(message)s'. Как настроить обработчики на отправку в консоль другого формата, чем в файл журнала? Методы, которые я опробовал, приводят к отправке обоих сообщений на консоль.

Ниже приведен один пример того, что НЕ работает:

    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s - %(message)s')
    console.setFormatter(formatter)
    root.addHandler(console)
    if sysout:
        handler = logging.StreamHandler(sys.stdout)
        handler.setLevel(logging.INFO)
        formatter = logging.Formatter('%(message)s')
        handler.setFormatter(formatter)
        root.addHandler(handler)

ЧАСТИЧНОЕ РЕШЕНИЕ:

В моей функции setup_logging я использую следующий код:

    logging.basicConfig(filename=abs_log_file, level=logging.DEBUG,
                        format='%(asctime)s - %(message)s')
    root = logging.getLogger()
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    formatter = logging.Formatter('%(message)s')
    console.setFormatter(formatter)
    root.addHandler(console)

... и в модуле, который вызывает setup_logging, у меня есть следующее:

# inhibits timestamps from printing to console logging.getLogger('').handlers[1].formatter._fmt = '%(message)s'

Работает по желанию, но я получаю предупреждение "Доступ к защищенному члену _fmt класса". Что такое совместимое решение?

1 Ответ

1 голос
/ 07 ноября 2019

У вас есть два обработчика:

  1. Обработчик с именем handler. Выходной поток для handler равен sys.stdout. handler печатает только сообщения без отметок времени.
  2. У вас есть обработчик с именем console. console печатает отметку времени и сообщение. Вы оставили выходной поток неуказанным.

Обратите внимание, что вы ничего не передавали в конструктор при написании console = logging.StreamHandler() По умолчанию цель StreamHandler - sys.stderr Ни один из ваших обработчиков не печатаетв файл. Один печатает на консоль через stdout, а другой печатает на консоль через stderr. Я предполагаю, что вы видите метки времени на консоли из канала stderr.


I recommend something like the following:

import logging
import sys

sysout = True
logger = logging.getLogger('simple_example')
logger.setLevel(logging.INFO)
file_handler = logging.FileHandler("mylog.log", delay=True)
# If delay is true, then file opening
# is deferred until the first call to emit().
#
# there's no need to open the file until
# records are read to be written
file_handler.setLevel(logging.INFO)
logger.addHandler(file_handler)
frmt_time_and_msg = logging.Formatter('%(asctime)s - %(message)s')
file_handler.setFormatter(frmt_time_and_msg)


if sysout:
    stdout_handler = logging.StreamHandler(sys.stdout)
    stdout_handler.setLevel(logging.INFO)
    msg_only = logging.Formatter('%(message)s')
    stdout_handler.setFormatter(msg_only)
    logger.addHandler(stdout_handler)


logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

Вывод, видимый на sys.stdout. Не то чтобы нет отметок времени:

info message
warn message
error message
critical message

Содержимое mylog.log:

2019-11-06 17:24:55,502 - info message
2019-11-06 17:24:55,508 - warn message
2019-11-06 17:24:55,508 - error message
2019-11-06 17:24:55,508 - critical message
...