Логирование с Logging в Python
Логирование работы кода одна из часто возникающих задач при написании многих скриптов. В Python для этого есть очень мощная библиотека Logging, но её корректная настройка требует опыта. Например, я привык к формату логов веб серверов — когда в файл пишется вместе с сообщением время события, некоторая служебная информация, а так же в отдельный файл пишутся только ошибки, плюс есть ротация логов.
В сети по использованию Logging примеров достаточно, но чтобы в итоге лог соответствовали моим требованиям, пришлось хорошенько погуглить, поэтому итоговым результатом решил поделиться.
У меня получился следующий код настройки логов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import logging from logging.handlers import RotatingFileHandler # настройка логирования # формат лога log_formatter = logging.Formatter('[%(asctime)s] [LINE:%(lineno)d] %(levelname)-8s: %(message)s', datefmt = '%Y-%m-%d %H:%M:%S') # полный лог файл file_handler = RotatingFileHandler('log/import.log', mode = 'a', maxBytes = 10485760, backupCount = 10, encoding = None, delay = 0) file_handler.setFormatter(log_formatter) file_handler.setLevel(logging.DEBUG) # лог файл только ошибок file_error_handler = RotatingFileHandler('log/error.log', mode = 'a', maxBytes = 10485760, backupCount = 10, encoding = None, delay = 0) file_error_handler.setFormatter(log_formatter) file_error_handler.setLevel(logging.ERROR) # инициализация логирования app_log = logging.getLogger('root') app_log.setLevel(logging.DEBUG) app_log.addHandler(file_handler) app_log.addHandler(file_error_handler) |
Опыт разработки на Python у меня пока небольшой, в основном пишу на PHP, поэтому вывод логов обернул еще в две функции — echo и echo_error:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# функции вывода сообщений вместе с их логированием def echo(text): print text app_log.info(text) def echo_error(text): print text app_log.error(text) mail(['почта получателя письма'], 'Ошибка импорта', 'Возникла ошибка в скрипте импорта Import.py:<br>' + text) # отправка сообщения на почту # Пример использования: echo('Connection closed.') echo_error('Тестовая ошибка') |
Но у этой обертки есть минус — номер строки lineno в log_formatter всегда указывает на вызов в самой функции echo (т.е. всегда одинаковый), а не на строку вызова функции. К тому же от этих кривоватых оберток можно вообще избавиться, добавив дополнительные хандлеры к объекту app_log — хандлер вывода в консоль и хандлер отправки письма на почту — в Logging они есть.
Так SMTPHandler позволяет отправить письмо по SMTP, но мне нужна была поддержка SSL и показалось проще/быстрее отправить письмо через SMTPlib. Об этом написал в предыдущем посте. Возможно позже сделаю эти доработки.
Если Вам такие сложности не нужны, и достаточно ведения простого лог файла, можно использовать такой код:
1 2 3 4 5 6 7 8 9 |
import logging logging.basicConfig(format = '[%(asctime)s] [LINE:%(lineno)d] %(levelname)-8s: %(message)s', datefmt = '%Y-%m-%d %H:%M:%S', filename = 'log/example.log', encoding = 'utf8', level = logging.DEBUG) # пример вызова logging.info('Root logger output') |
Источники:
Официальная документация: https://docs.python.org/2/library/logging.html и https://docs.python.org/2/library/logging.handlers.html
Небольшой пример с хабра, с которого взял пример форматирования: https://habrahabr.ru/post/144566/
Хороший пример с кучей различных настроек: https://fangpenlin.com/posts/2012/08/26/good-logging-practice-in-python/