В модуле 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




