В модуле logging
используются четыре основных класса, которые нас интересуют:
- Loggers – используются приложением для передачи сообщений системе логирования;
- Formatters – форматирование сообщений;
- Filters – фильтрация сообщений;
- Handlers – отправка форматированных сообщений в определённом направлении, например – в файл.
Далее мы кратко рассмотрим создание Logger
, Handler
и Formatter
.
Для создания объекта-логгера достаточно указать:
log = logging.getLogger(__name__)
Такое создание логгера создаст объект с именем, отвечающим имени модуля, в котором он создаётся, что потом поможет разобраться в логах.
Создадим простой скрипт:
#!/usr/bin/env python # -*- coding: utf-8 -*- # импортируем модуль import logging # задаём уровень логгирования logging.basicConfig(level=logging.INFO) # создаём объект с именем модуля logger = logging.getLogger(__name__) # логгируем запись на уровне INFO logger.info('Start logging INFO')
И результат его выполнения:
$ ./logger1.py INFO:__main__:Start logging INFO
Для каждого события можно указать уровень важности:
CRITICAL
ERROR
WARNING
INFO
DEBUG
NOTSET
Меняя уровень важности для Logger
или Handler
-а – можно устанавливать, какие данные заносить в лог – а какие нет:
#!/usr/bin/env python # -*- coding: utf-8 -*- # импортируем модуль import logging # задаём уровень логгирования logging.basicConfig(level=logging.INFO) # создаём объект с именем модуля logger = logging.getLogger(__name__) # логгируем запись на уровне INFO logger.info('Start logging INFO') # добавлем запись на уровне DEBUG logger.debug('Start logging DEBUG')
Так как в параметрах логгера (logging.basicConfig
) задан уровень важности INFO
– то запись с уровнем DEBUG
не пройдёт:
$ ./logger1.py INFO:__main__:Start logging INFO
Если же изменить уровень на DEBUG:
logging.basicConfig(level=logging.DEBUG)
То:
$ ./logger1.py INFO:__main__:Start logging INFO DEBUG:__main__:Start logging DEBUG
Далее, добавим использование FileHandler
, что бы использовать запись в файл, и Formatter
– что бы настроить формат записей в файле:
#!/usr/bin/env python # -*- coding: utf-8 -*- # импортируем модуль import logging # создаём объект с именем модуля logger = logging.getLogger(__name__) # задаём уровень логгирования logger.setLevel(logging.INFO) # создаём обрабочтик файла лога handler = logging.FileHandler('logger1.log') # задаём уровень логгирования handler.setLevel(logging.INFO) # форматируем записи formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # устанавливаем формат для обработчика handler.setFormatter(formatter) # добавляем обработчик к логгеру logger.addHandler(handler) # записываем сообщение logger.info('Hello baby')
Проверяем файл:
$ cat logger1.log 2015-01-28 13:14:38,834 - __main__ - INFO - Hello baby
Запись логов из разных модулей
Создадим script1
:
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging import script2 logging.basicConfig(level=logging.INFO) if __name__ == '__main__': logging.info('Started script 1') script2.somefunc() logging.info('Finished script 1')
И script2
:
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging def somefunc (): logging.info('Started script 2')
Запускаем script1
:
$ ./script1.py INFO:root:Started script 1 INFO:root:Started script 2 INFO:root:Finished script 1
Усложним логгирование, что бы каждый модуль записывал своё имя в лог:
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging import script2 logging.basicConfig(level=logging.INFO) if __name__ == '__main__': logger = logging.getLogger(__name__) logger.info('Started script 1') script2.somefunc() logger.info('Finished script 1')
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging def somefunc (): logger = logging.getLogger(__name__) logger.info('Started script 2')
Результат:
$ ./script1.py INFO:__main__:Started script 1 INFO:script2:Started script 2 INFO:__main__:Finished script 1
Таким образом, каждый модуль программы будет задавать своё имя в логе.
Добавим запись в файл и форматирование:
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging import script2 logging.basicConfig(filename='logger.log', level=logging.INFO, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s') if __name__ == '__main__': logger = logging.getLogger(__name__) logger.info('Started script 1') script2.somefunc() logger.info('Finished script 1')
И script2
:
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging def somefunc (): logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) logger.info('Started script 2') # эта строка не попадёт в лог logger.debug('Started Script 2 DEBUG')
Проверяем:
$ ./script1.py
$ cat logger.log 2015-01-28 13:48:23,410 __main__ INFO Started script 1 2015-01-28 13:48:23,411 script2 INFO Started script 2 2015-01-28 13:48:23,411 __main__ INFO Finished script 1
Кроме записи в файл – можно сделать вывод сообщений на консоль, вместо использования print()
.
Добавим StreamHandler
и FileHandler
:
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s') console = logging.StreamHandler() console.setLevel(logging.WARNING) console.setFormatter(formatter) filehandler = logging.FileHandler('logger.log') filehandler.setLevel(logging.INFO) filehandler.setFormatter(formatter) logger.addHandler(console) logger.addHandler(filehandler) if __name__ == '__main__': logger.info('Started logging') # эта строка пойдёт и в файл и на консоль logger.warning('Started logging to console and log') logger.info('Finished logging')
Результат:
$ ./script1.py 2015-01-28 14:07:47,089 __main__ WARNING Started logging to console and log
$ cat logger.log 2015-01-28 14:07:47,088 __main__ INFO Started logging 2015-01-28 14:07:47,089 __main__ WARNING Started logging to console and log 2015-01-28 14:07:47,089 __main__ INFO Finished logging
Возможностей у модуля logging
очень много, поэтому – ссылки по теме:
http://pieces.openpolitics.com