Автор оригинала: Doug Hellmann.
Цель:
Сообщать о состоянии, ошибках и информационных сообщениях.
Модуль logging
определяет стандартный API для отчетов об ошибках и информации о состоянии из приложений и библиотек. Ключевым преимуществом наличия API журналирования, предоставляемого стандартным библиотечным модулем, является то, что все модули Python могут участвовать в журналировании, поэтому журнал приложения может включать сообщения от сторонних модулей.
Компоненты ведения журнала
Система регистрации состоит из четырех взаимодействующих типов объектов. Каждый модуль или приложение, которое хочет вести журнал, использует экземпляр Logger
для добавления информации в журналы. При вызове регистратора создается LogRecord
, который используется для хранения информации в памяти до ее обработки. Logger
может иметь несколько объектов Handler
, настроенных для получения и обработки записей журнала.
Вход в приложения и библиотеки
Разработчики приложений и авторы библиотек могут использовать ведение журнала
, но у каждой аудитории есть свои соображения, о которых следует помнить.
Разработчики приложений настраивают модуль logging
, направляя сообщения в соответствующие выходные каналы. Можно регистрировать сообщения с разной степенью детализации или по разным адресатам. Включены обработчики для записи сообщений журнала в файлы, местоположения HTTP GET/POST, электронная почта через SMTP, общие сокеты или механизмы ведения журнала для конкретной ОС, и можно создавать собственные классы назначения журнала для особых требований, которые не обрабатываются.
Разработчики библиотек также могут использовать ведение журнала
, и у них еще меньше работы. Просто создайте экземпляр регистратора для каждого контекста, используя соответствующее имя, а затем регистрируйте сообщения, используя стандартные уровни. Пока библиотека использует API ведения журнала с согласованным именованием и выбором уровней, приложение
Вход в файл
Большинство приложений настроены для входа в файл. Используйте функцию basicConfig ()
, чтобы настроить обработчик по умолчанию, чтобы сообщения отладки записывались в файл.
logging_file_example.py
import logging LOG_FILENAME 'logging_example.out' logging.basicConfig( filenameLOG_FILENAME, levellogging.DEBUG, ) logging.debug('This message should go to the log file') with open(LOG_FILENAME, 'rt') as f: body f.read() print('FILE:') print(body)
После запуска сценария сообщение журнала записывается в logging_example.out
:
$ python3 logging_file_example.py FILE: DEBUG:root:This message should go to the log file
Ротация файлов журнала
Многократный запуск сценария приводит к добавлению дополнительных сообщений к файлу. Чтобы создавать новый файл при каждом запуске программы, передайте аргумент filemode
в basicConfig ()
со значением 'w'
. Однако вместо того, чтобы управлять созданием файлов таким образом, лучше использовать RotatingFileHandler
, который автоматически создает новые файлы и сохраняет при этом старый файл журнала.
logging_rotatingfile_example.py
import glob import logging import logging.handlers LOG_FILENAME 'logging_rotatingfile_example.out' # Set up a specific logger with our desired output level my_logger logging.getLogger('MyLogger') my_logger.setLevel(logging.DEBUG) # Add the log message handler to the logger handler logging.handlers.RotatingFileHandler( LOG_FILENAME, maxBytes20, backupCount5, ) my_logger.addHandler(handler) # Log some messages for i in range(20): my_logger.debug('i = %d' % i) # See what files are created logfiles glob.glob('%s*' % LOG_FILENAME) for filename in sorted(logfiles): print(filename)
В результате получается шесть отдельных файлов, каждый из которых содержит часть истории журнала для приложения.
$ python3 logging_rotatingfile_example.py logging_rotatingfile_example.out logging_rotatingfile_example.out.1 logging_rotatingfile_example.out.2 logging_rotatingfile_example.out.3 logging_rotatingfile_example.out.4 logging_rotatingfile_example.out.5
Самый последний файл – это всегда logging_rotatingfile_example.out
, и каждый раз, когда он достигает предельного размера, он переименовывается с суффиксом .1
. Каждый из существующих файлов резервных копий переименовывается, чтобы увеличить суффикс ( .1
становится .2
и т. Д.), А файл .5
удаляется.
Примечание
Очевидно, что в этом примере длина журнала слишком мала в качестве крайнего примера. Установите для maxBytes
более подходящее значение в реальной программе.
Уровни детализации
Еще одна полезная функция logging
API – это возможность создавать разные сообщения на разных уровнях журнала . Это означает, что код можно оснастить, например, сообщениями отладки, а уровень журнала можно установить так, чтобы эти сообщения отладки не записывались в производственной системе. в таблице ниже перечислены уровни ведения журнала, определенные logging
.
Уровни регистрации
Уровень
Ценить
КРИТИЧЕСКИЙ
50
ОШИБКА
40
ПРЕДУПРЕЖДЕНИЕ
30
ИНФОРМАЦИЯ
20
ОТЛАЖИВАТЬ
10
UNSET
Сообщение журнала создается только в том случае, если обработчик и средство ведения журнала настроены на отправку сообщений этого уровня или выше. Например, если сообщение имеет тип CRITICAL
и для регистратора установлено значение ERROR
, сообщение будет отправлено (50> 40). Если сообщение представляет собой WARNING
, а регистратор настроен на создание только сообщений, для которых установлено значение ERROR
, сообщение не отправляется.
logging_level_example.py
import logging import sys LEVELS { 'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING, 'error': logging.ERROR, 'critical': logging.CRITICAL, } if len(sys.argv) > 1: level_name sys.argv[1] level LEVELS.get(level_name, logging.NOTSET) logging.basicConfig(levellevel) logging.debug('This is a debug message') logging.info('This is an info message') logging.warning('This is a warning message') logging.error('This is an error message') logging.critical('This is a critical error message')
Запустите сценарий с аргументом вроде «отладка» или «предупреждение», чтобы узнать, какие
$ python3 logging_level_example.py debug DEBUG:root:This is a debug message INFO:root:This is an info message WARNING:root:This is a warning message ERROR:root:This is an error message CRITICAL:root:This is a critical error message $ python3 logging_level_example.py info INFO:root:This is an info message WARNING:root:This is a warning message ERROR:root:This is an error message CRITICAL:root:This is a critical error message
Именование экземпляров регистратора
Все предыдущие сообщения журнала имеют встроенный «root», потому что код использует корневое средство ведения журнала. Простой способ узнать, откуда приходит конкретное сообщение журнала, – это использовать отдельный объект журнала для каждого модуля. Сообщения журнала, отправляемые регистратору, включают имя этого регистратора. Вот пример того, как вести журнал из разных модулей, чтобы можно было легко отследить источник сообщения.
logging_modules_example.py
import logging logging.basicConfig(levellogging.WARNING) logger1 logging.getLogger('package1.module1') logger2 logging.getLogger('package2.module2') logger1.warning('This message comes from one module') logger2.warning('This comes from another module')
Выходные данные показывают разные имена модулей для каждой выходной строки.
$ python3 logging_modules_example.py WARNING:package1.module1:This message comes from one module WARNING:package2.module2:This comes from another module
Дерево регистрации
Экземпляры Logger
настроены в виде древовидной структуры на основе их имен, как показано на рисунке. Обычно каждое приложение или библиотека определяет базовое имя, а регистраторы для отдельных модулей устанавливаются как дочерние. У корневого регистратора нет имени.
Пример дерева регистратора
Древовидная структура полезна для настройки ведения журнала, поскольку она означает, что каждому регистратору не нужен собственный набор обработчиков. Если регистратор не имеет обработчиков, сообщение передается его родительскому объекту для обработки. Это означает, что для большинства приложений необходимо настроить обработчики только на корневом регистраторе, и вся информация журнала будет собираться и отправляться в одно и то же место, как показано на рисунке.
Один обработчик журналов
Древовидная структура также позволяет устанавливать различные уровни детализации, обработчики и средства форматирования для разных частей приложения или библиотеки, чтобы контролировать, какие сообщения регистрируются и куда они направляются, как показано на рисунке.
Различные уровни и обработчики
Интеграция с модулем предупреждений
Модуль ведения журнала интегрируется с предупреждениями через captureWarnings ()
, который настраивает предупреждения
для отправки сообщений через систему ведения журнала вместо их вывода напрямую.
logging_capture_warnings.py
import logging import warnings logging.basicConfig( levellogging.INFO, ) warnings.warn('This warning is not sent to the logs') logging.captureWarnings(True) warnings.warn('This warning is sent to the logs')
Предупреждение отправляется регистратору с именем py.warnings
с использованием уровня WARNING
.
$ python3 logging_capture_warnings.py logging_capture_warnings.py:13: UserWarning: This warning is not sent to the logs warnings.warn('This warning is not sent to the logs') WARNING:py.warnings:logging_capture_warnings.py:17: UserWarning: This warning is sent to the logs warnings.warn('This warning is sent to the logs')
Смотрите также
- стандартная библиотека документации для ведения журнала . Документация для
ведения журнала
обширна и включает учебные пособия и справочные материалы, выходящие за рамки представленных здесь примеров. - Python