Настройка логирования в Python: вывод всех сообщений в stdout и файл журнала
Как решить проблему с логированием в Python с использованием модуля logging
? Мне нужно, чтобы все сообщения автоматически выводились как в файл журнала, так и в stdout
. Например, я хочу, чтобы все вызовы logger.warning
, logger.critical
, logger.error
записывались в соответствующие места, но при этом дублировались в stdout
. Это нужно для того, чтобы избежать переписывания сообщений, как в следующем примере:
mylogger.critical("что-то не удалось")
print("что-то не удалось")
Хотелось бы узнать, как это можно реализовать?
5 ответ(ов)
Да, это возможно с использованием нескольких обработчиков (handlers) в модуле logging
. Ниже представлен пример, который демонстрирует создание логгера с записью логов как в файл, так и в консоль с разными уровнями детализации.
import logging
import auxiliary_module
# создаем логгер с именем 'spam_application'
log = logging.getLogger('spam_application')
log.setLevel(logging.DEBUG)
# создаем форматтер и добавляем его к обработчикам
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# создаем обработчик для записи логов в файл, который будет фиксировать даже сообщения отладочного уровня
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
log.addHandler(fh)
# создаем обработчик для вывода логов в консоль с более высоким уровнем
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
ch.setFormatter(formatter)
log.addHandler(ch)
log.info('создание экземпляра auxiliary_module.Auxiliary')
a = auxiliary_module.Auxiliary()
log.info('экземпляр auxiliary_module.Auxiliary создан')
log.info('вызов auxiliary_module.Auxiliary.do_something')
a.do_something()
log.info('завершен вызов auxiliary_module.Auxiliary.do_something')
log.info('вызов auxiliary_module.some_function()')
auxiliary_module.some_function()
log.info('вызов auxiliary_module.some_function() завершен')
# не забудьте закрыть обработчики
for handler in log.handlers:
handler.close()
log.removeFilter(handler)
Обратите внимание, что мы используем FileHandler
, чтобы записывать все сообщения уровня DEBUG и выше в файл spam.log
, и StreamHandler
, чтобы выводить только сообщения уровня ERROR и выше в консоль. Это позволяет гибко управлять тем, какие сообщения вы хотите фиксировать и отображать. Подробности можно найти в документации Python.
Для того чтобы просто записывать логи как в файл, так и в стандартный поток ошибок (stderr), вы можете использовать следующий код:
import logging
# Настройка базовой конфигурации логирования с указанием файла
logging.basicConfig(filename="logfile.txt")
# Создаем обработчик для вывода логов на stderr
stderrLogger = logging.StreamHandler()
stderrLogger.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
# Добавляем обработчик stderr к корневому логгеру
logging.getLogger().addHandler(stderrLogger)
Этот код сначала настраивает логирование в файл logfile.txt
, а затем создает дополнительный обработчик, который выводит логи в стандартный поток ошибок. Таким образом, вы получите логи как в файл, так и в консоль.
Поскольку никто не поделился компактным двустрочным решением, я решил представить своё:
logging.basicConfig(filename='logs.log', level=logging.DEBUG, format="%(asctime)s:%(levelname)s: %(message)s")
logging.getLogger().addHandler(logging.StreamHandler())
Этот код настраивает логирование в файл logs.log
с уровнем отладки и добавляет потоковый обработчик для вывода логов в консоль.
Вот крайне простой пример использования модуля logging
в Python:
import logging
l = logging.getLogger("test")
# Добавляем обработчик для записи в файл
f = logging.FileHandler("test.log")
l.addHandler(f)
# Добавляем обработчик для вывода в поток (stdout)
s = logging.StreamHandler()
l.addHandler(s)
# Отправляем тестовое сообщение в оба обработчика — уровень "critical" всегда будет логироваться
l.critical("test msg")
Вывод будет показывать сообщение "test msg" как в стандартном выводе (stdout), так и в файле test.log
.
Вот простой, но явный способ настроить логирование в Python:
import logging
import sys
# Создаем логгер с именем текущего модуля
logger: logging.Logger = logging.getLogger(__name__)
# Добавляем обработчик для записи логов в файл
logger.addHandler(logging.FileHandler(f"{__name__}.log"))
# Добавляем обработчик для вывода логов в стандартный вывод
logger.addHandler(logging.StreamHandler(sys.stdout))
В этом коде мы создаем логгер, который будет записывать логи как в файл с именем текущего модуля, так и выводить их в консоль. Это позволяет легко отслеживать события как во время разработки, так и в конечном приложении.
Сохранение сообщений об исключениях в Python
Как зарегистрировать ошибку в Python с отладочной информацией?
Конфигурация логгера для записи в файл и вывода на stdout
Как изменить порядок столбцов в DataFrame?
Как проверить тип NoneType в Python?