6

Конфигурация логгера для записи в файл и вывода на stdout

7

Я использую модуль logging в Python для записи строк отладки в файл, и это работает довольно хорошо. Теперь я хотел бы дополнительно использовать этот модуль для вывода строк в стандартный вывод (stdout). Как мне это сделать? Для записи строк в файл я использую следующий код:

import logging
import logging.handlers

logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)

handler = logging.handlers.RotatingFileHandler(
    LOGFILE, maxBytes=(1048576*5), backupCount=7
)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)

Затем я вызываю функцию логирования следующим образом:

logger.debug("Я записан в файл")

Спасибо за помощь!

5 ответ(ов)

7

Чтобы добавить обработчик вывода логов в Python, можно просто получить корневой логгер и добавить к нему StreamHandler. Этот обработчик по умолчанию записывает сообщения в stderr. Если вам действительно нужно, чтобы сообщения выводились в stdout вместо stderr, просто укажите это при создании StreamHandler.

Вот пример, который можно использовать:

import logging

# Создаем корневой логгер и добавляем обработчик для вывода в stderr
logging.getLogger().addHandler(logging.StreamHandler())

Если хотите выводить логи в stdout, сделайте так:

import sys
# ...
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))

Также вы можете добавить Formatter для форматирования всех записей логов с общим заголовком, например:

import logging

logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s")
rootLogger = logging.getLogger()

# Добавляем обработчик, который будет писать логи в файл
fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)

# Добавляем обработчик для вывода в консоль
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)

Такой код будет выводить сообщения в формате:

2012-12-05 16:58:26,618 [MainThread  ] [INFO ]  my message

Теперь у вас есть логирование как в файл, так и в консоль с одинаковым форматом сообщений.

0

Когда вы добавляете StreamHandler без указания аргументов, он по умолчанию использует stderr вместо stdout. Если другой процесс зависит от вывода в stdout (например, при написании плагина NRPE), убедитесь, что вы явно указываете stdout, иначе вы можете столкнуться с неожиданными проблемами.

Вот простой пример, который использует предполагаемые значения и переменную LOGFILE из вашего вопроса:

import logging
from logging.handlers import RotatingFileHandler
from logging import handlers
import sys

log = logging.getLogger('')
log.setLevel(logging.DEBUG)
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")

ch = logging.StreamHandler(sys.stdout)  # Явное указание на использование stdout
ch.setFormatter(format)
log.addHandler(ch)

fh = handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
fh.setFormatter(format)
log.addHandler(fh)

В этом коде мы создаем логгер, который отправляет сообщения как в stdout, так и в файл с помощью RotatingFileHandler. Обязательно указывайте sys.stdout, чтобы избежать путаницы с выводом.

0

Вы можете либо вызвать basicConfig с аргументом stream=sys.stdout до настройки других обработчиков или записи каких-либо сообщений, либо вручную добавить StreamHandler, который будет отправлять сообщения в stdout к корневому логгеру (или любому другому логгеру, который вам нужен).

0

Чтобы настроить логирование в Python так, чтобы сообщения выводились в stdout и в файл с ротацией, следуя разным уровням и форматам, вы можете использовать следующий код:

import logging
import logging.handlers
import sys

if __name__ == "__main__":
    # Изменяем уровень корневого логгера с WARNING (по умолчанию) на NOTSET, чтобы все сообщения обрабатывались.
    logging.getLogger().setLevel(logging.NOTSET)

    # Добавляем обработчик для вывода в stdout с уровнем INFO
    console = logging.StreamHandler(sys.stdout)
    console.setLevel(logging.INFO)
    formatter = logging.Formatter('%(name)-13s: %(levelname)-8s %(message)s')
    console.setFormatter(formatter)
    logging.getLogger().addHandler(console)

    # Добавляем обработчик для ротации файла с уровнем DEBUG
    rotatingHandler = logging.handlers.RotatingFileHandler(filename='rotating.log', maxBytes=1000, backupCount=5)
    rotatingHandler.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    rotatingHandler.setFormatter(formatter)
    logging.getLogger().addHandler(rotatingHandler)

    log = logging.getLogger("app." + __name__)

    log.debug('Debug message, should only appear in the file.')
    log.info('Info message, should appear in file and stdout.')
    log.warning('Warning message, should appear in file and stdout.')
    log.error('Error message, should appear in file and stdout.')

Объяснение кода:

  1. Уровень логирования: Изменяем уровень корневого логгера на NOTSET, чтобы все сообщения обрабатывались.
  2. Обработчик для stdout: Создаем StreamHandler, который будет выводить сообщения уровня INFO и выше в стандартный вывод (stdout). Формат сообщений задается с помощью Formatter.
  3. Обработчик для файла: Используем RotatingFileHandler, чтобы логировать сообщения уровня DEBUG и выше в файл rotating.log. Если размер файла превышает 1000 байт, он будет ротироваться, сохраняя до 5 резервных копий. Формат сообщений для файла отличается от формата для консоли.
  4. Логирование сообщений: В конце демонстрируется, как различные уровни логирования будут выводиться в консоль и файл.

Таким образом, с помощью вышеописанного кода вы сможете одновременно вести логирование как в stdout, так и в файл, используя разные уровни и форматы сообщений.

0

После многократного использования кода Waterboy в различных пакетах Python, я наконец создал небольшой самостоятельный пакет Python, который вы можете найти здесь:

https://github.com/acschaefer/duallog

Код хорошо документирован и легко в использовании. Просто скачайте файл .py и добавьте его в свой проект, или установите весь пакет с помощью команды pip install duallog.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь