Автор статьи: Жульен Данжу (Julien Danjou). Оригинал: https://julien.danjou.info/python-logging-easy-with-daiquiri/
За 10 с лишним лет, именно столько я пишу программы на Python, меня всегда раздражала одна вещь в нем — его протоколирование.
Не поймите меня неправильно, мне нравится подсистема протоколирования Python. Ею легко пользоваться и она замечательно работает во многих случаях. Наверное, если вы никогда не пользовались ею, то вначале может даже показаться, что протоколирование в Python это очень просто:
import logging
logger = logging.getLogger()
logger.info("Something useful")
Вряд ли ведь что-то может быть еще проще! Но что меня расстраивает, это то, что если вы запустите этот пример, произойдет ошибка. Смотрите сами:
>>> import logging
>>> logger = logging.getLogger()
>>> logger.error("Something useful")
No handlers could be found for logger "root"
Ничего не выводится, только ошибка. Файл протокола (журнала с сообщениями, лога) не записался. «По умолчанию» это не работает. Мне это совсем не нравится.
Каждый раз, когда я пишу новое приложение, нужно запоминать все его настройки. Да, конечно, есть полная документация по API, в которой подробно объясняется как настроить обработчики, форматирование, фильтры или фабрику записей сообщений. Но мне постоянно приходится копаться в ней, чтобы вспомнить, как выставить некоторые параметры значений по умолчанию (например, вывод протокола в поток stderr, используя при этом формат с отметкой времени). Конечно, можно для этого использовать функцию logging.basicConfig, но обычно, с ее помощью мало что можно настроить (например, нельзя напечатать те же метки времени).
Снова и снова, мне приходится выполнять одни и те же действия, когда я настраиваю протоколирование.
А вот и она, daiquiri
Недавно я, наконец-то, нашел свободное время и написал крошечную библиотеку, которая бы делала эту работу за меня. Она называется daiquiri и служит только для одного: настройки встроенной подсистемы Python для протоколирования сообщений в современных программах.
Она небольшая. Версия 1.0.0, которую я выпустил, содержит всего 228 строк кода и 79 строк тестов. И это все!
Она обещает полностью настроить стандартную систему протоколирования Python за вызов всего лишь одной функции. Ни больше и ни меньше. Самые интересные ее особенности, это:
запись протокола в stderr по умолчанию;
при протоколировании сообщений в терминал можно использовать разные цвета;
поддерживается запись протокола в файл;
можно использовать имя программы в качестве имени файла протокола, при этом достаточно указать каталог, куда будут записываться файлы;
поддерживается запись в syslog или journald;
поддерживается вывод в формат JSON;
поддерживается использование произвольных пар «ключ-значение» при обмене контекстной информацией;
отлов предупреждений, выпущенные модулем warnings;
собственная система протоколирования любых исключений.
Давайте посмотрим, как же она это все делает без настройки!
Основная работа библиотеки
Вот, что нужно написать, чтобы начать работать с daiquiri:
import daiquiri
daiquiri.setup()
Как я вам уже сказал, хочу, чтобы все было легко. Просто, если делать это с ее помощью, то это намного лучше, чем мучиться с logging.basicConfig. И что-то полезное печатается сразу, как и должно быть:
>>> import daiquiri
>>> daiquiri.setup()
>>> logger = daiquiri.getLogger()
>>> logger.error("something wrong happened")
2017-07-04 18:03:04,929 [16876] ERROR root: something wrong happened
Она выводит сообщения в поток stderr, применяя для этого необходимое форматирование и временную метку по умолчанию. Ведь это, как раз то, что все хотят, не так ли? Если вы запустите это в терминале, строка будет красной, так как это ошибка, и она будет зарегистрирована. Для разных уровней критичности сообщений будут использоваться другие цвета (например, зеленый для debug и т. п.).
Кроме этого, daiquiri зарегистрирует любое исключение, произошедшее в вашей программе:
>>> import daiquiri
>>> daiquiri.setup()
>>> raise Exception("boom!")
2017-07-04 18:05:43,378 [16959] CRITICAL root: Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception: boom!
Если по какой-то причине исключение не получается обработать, тогда в журнале появится предупреждающее сообщение.
Другие возможности библиотеки
Если хотите изменить запись сообщений в протокол по умолчанию, вы можете сделать это, просто передав некоторые аргументы в функцию daiquiri.setup. Она принимает аргумент outputs, который должен быть перечислением объектов типа daiquiri.Output. Как правило, в этот список включаются, следующие объекты: daiquiri.File для протоколирования в файл, daiquiri.Syslog — в syslog или daiquiri.Stream — в любой другой поток (например: открытый файл, stdout или stderr).
Если вы хотите протоколировать непосредственно в syslog или же в stderr, то вот, как это сделать:
daiquiri.setup(outputs=(
daiquiri.output.Syslog(),
daiquiri.output.STDERR,
))
А если желаете записать протокол в файл, достаточно просто указать каталог, и daiquiri создаст в нем одноименный файл для вашей программы:
# Если имя вашей программы foobar-server, тогда файл протокола
# будет создан в /var/log/foobar-server.log
daiquiri.setup(outputs=(
daiquiri.output.File(directory="/var/log"),))
Соглашусь, что это слишком простые примеры. Так, давайте же запишем протокол в journald, а также на сетевой сервер, используя для этого вывод в JSON:
import socket
import daiquiri
# Давайте сначала подключимся к серверу
s = socket.socket()
# Вы можете запустить простой сервер, написав в терминале: `nc -l 2333`
s.connect(("localhost", 2333))
f = s.makefile()
daiquiri.setup(outputs=(
daiquiri.output.Journal(),
daiquiri.output.Stream(f, formatter=daiquiri.formatter.JSON_FORMATTER),
))
daiquiri.getLogger().error("oops", somekey=42, anotherkey="foobar")
# Сервер получит:
# {"message": "oops", "somekey": 42, "anotherkey": "foobar"}
Конечно же, вывод информации можно дополнить, применив для этого свое собственное форматирование для записей — API daiquiri довольно прост. Но в 99% написанных приложений, используются только стандартные настройки.
Вы можете свободно установить библиотеку с помощью pip или клонировать с помощью git! Она доступна на PyPI, ее исходники находятся на GitHub, а документация опубликована в Интернете.