справочник по Python. мм isbn 9785932861578 9 785932 861578
Скачать 4.21 Mb.
|
453 import logging # Регистратор ‘app’ верхнего уровня. log = logging.getLogger(‘app’) log.setLevel(logging.CRITICAL) # Принимает только сообщения с уровнем CRITICAL ёё # Дочерний регистратор ‘app.net’ net_log = logging.getLogger(‘app.net’) net_log.setLevel(logging.ERROR) # Принимает сообщения с уровнем ERROR # Сообщения, переданные ‘app.net’, # теперь будут обрабатываться # регистратором ‘app’, несмотря на то, что # он имеет уровень CRITICAL. При использовании иерархий регистраторов достаточно настроить только те объекты регистраторов, которые отличаются наборами фильтров или поддержкой механизма распространения сообщений. Распространение сообщения заканчивается в корневом регистраторе, поэтому он несет всю ответственность за вывод сообщения с учетом настроек, которые были вы- полнены с помощью функции basicConfig(). Обработка сообщений Обычно сообщения обрабатываются корневым регистратором. Однако лю- бой объект класса Logger может иметь свои специальные обработчики, при- нимающие и обрабатывающие сообщения. Реализовать это можно с помо- щью следующих методов экземпляра log класса Logger. log.addHandler(handler) Добавляет объект класса Handler в регистратор. log.removeHandler(handler) Удаляет объект класса Handler из регистратора. В модуле logging имеется множество различных предопределенных обра- ботчиков, выполняющих запись сообщений в файлы, потоки, в системный журнал и так далее. Подробнее об этом рассказывается в следующем разде- ле. Следующий пример демонстрирует, как подключать обработчики к ре- гистраторам с помощью указанных выше методов. import logging import sys ёё # Создать регистратор верхнего уровня с именем ‘app’ app_log = logging.getLogger(“app”) app_log.setLevel(logging.INFO) app_log.propagate = False ёё # Добавить несколько обработчиков в регистратор ‘app’ app_log.addHandler(logging.FileHandler(‘app.log’)) app_log.addHandler(logging.StreamHandler(sys.stderr)) ёё # Отправить несколько сообщений. Они попадут в файл app.log # и будут выведены в поток sys.stderr app_log.critical(“Creeping death detected!”) app_log.info(“FYI”) 454 Глава 19. Службы операционной системы Чаще всего добавление собственных обработчиков сообщений в регистра- тор выполняется с целью переопределить поведение корневого регистра- тора. Именно по этой причине в примере был отключен механизм распро- странения сообщений (то есть регистратор ‘app’ сам будет обрабатывать все сообщения). Объекты класса Handler Модуль logging предоставляет целую коллекцию предопределенных обра- ботчиков для обработки сообщений различными способами. Эти обработ- чики добавляются в объекты класса Logger с помощью метода addHandler(). Кроме того, для каждого обработчика можно установить свой уровень важ- ности и фильтры. Встроенные обработчики Ниже перечислены встроенные объекты обработчиков. Некоторые из них определяются в подмодуле logging.handlers, который, в случае необходимо- сти, должен импортироваться отдельно. handlers.DatagramHandler(host,port) Отправляет сообщения по протоколу UDP на сервер с именем host и в порт port . Сообщения кодируются с применением соответствующего объекта словаря LogRecord и переводятся в последовательную форму с помощью мо- дуля pickle. Сообщение, передаваемое в сеть, состоит из 4-байтового значе- ния длины (с прямым порядком следования байтов), за которым следует упакованная запись с данными. Чтобы реконструировать сообщение, при- емник должен отбросить заголовок с длиной, прочитать сообщение, распа- ковать его содержимое с помощью модуля pickle и вызвать функцию log- ging.makeLogRecord() . Так как протокол UDP является ненадежным, ошиб- UDP является ненадежным, ошиб- является ненадежным, ошиб- ки в сети могут привести к потере сообщений. FileHandler(filename [, mode [, encoding [, delay]]]) Выводит сообщения в файл с именем filename. Аргумент mode определяет режим открытия файла и по умолчанию имеет значение ‘a’. В аргументе encoding передается кодировка. В аргументе delay передается логический флаг; если он имеет значение True, открытие файла журнала откладывает- ся до появления первого сообщения. По умолчанию имеет значение False. handlers.HTTPHandler(host, url [, method]) Выгружает сообщения на сервер HTTP, используя метод HTTP GET или POST . Аргумент host определяет имя хоста, url – используемый адрес URL, а method – метод HTTP, который может принимать значение ‘GET’ (по умол- чанию) или ‘POST’. Сообщения кодируются с применением соответствую- щего объекта словаря LogRecord и преобразуются в переменные строки за- проса URL с помощью функции urllib.urlencode(). handlers.MemoryHandler(capacity [, flushLevel [, target]]) Этот обработчик используется для сбора сообщений в памяти и периоди- ческой передачи другому обработчику, который определяется аргументом target . Аргумент capacity определяет размер буфера в байтах. В аргументе Модуль logging 455 flushLevel передается числовое значение уровня важности. Когда появляет- передается числовое значение уровня важности. Когда появляет- числовое значение уровня важности. Когда появляет- числовое значение уровня важности. Когда появляет- значение уровня важности. Когда появляет- значение уровня важности. Когда появляет- уровня важности. Когда появляет- уровня важности. Когда появляет- важности. Когда появляет- важности. Когда появляет- . Когда появляет- Когда появляет- ся сообщение с указанным уровнем или выше, это вынуждает обработчик передать содержимое буфера дальше. По умолчанию используется значе- умолчанию используется значе- умолчанию используется значе- используется значе- используется значе- значе- значе- ние ERROR. В аргументе target передается объект класса Handler, принимаю- щий сообщения. Если аргумент target опущен, вам придется определить объект-обработчик с помощью метода setTarget(), чтобы он мог выполнять обработку. handlers.NTEventLogHandler(appname [, dllname [, logtype]]) В Windows NT, Windows 2000 или Windows XP отправляет сообщения в системный журнал событий. В аргументе appname передается имя прило- жения, которое будет записываться в журнал событий. В аргументе dllname передается полный путь к файлу .DLL или .EXE, в котором хранятся опре- DLL или .EXE, в котором хранятся опре- или .EXE, в котором хранятся опре- EXE, в котором хранятся опре- , в котором хранятся опре- деления сообщений для журнала событий. Если аргумент опущен, dllname получает значение ‘win32service.pyd’. В аргументе logtype можно передать одно из значений: ‘Application’, ‘System’ или ‘Security’. По умолчанию ис- умолчанию ис- умолчанию ис- ис- ис- пользуется значение ‘Application’. Этот обработчик доступен, только если были установлены расширения Win32 для Python. handlers.RotatingFileHandler(filename [, mode [, maxBytes [, backupCount [, encoding [, delay]]]]]) Выводит сообщение в файл filename. Если размер этого файла превысит значение в аргументе maxBytes, он будет переименован в filename.1 и будет открыт новый файл с именем filename. Аргумент backupCount определяет максимальное количество резервных копий файла. По умолчанию аргу- количество резервных копий файла. По умолчанию аргу- количество резервных копий файла. По умолчанию аргу- резервных копий файла. По умолчанию аргу- резервных копий файла. По умолчанию аргу- копий файла. По умолчанию аргу- копий файла. По умолчанию аргу- файла. По умолчанию аргу- файла. По умолчанию аргу- . По умолчанию аргу- По умолчанию аргу- умолчанию аргу- умолчанию аргу- аргу- аргу- мент backupCount имеет значение 0. При любом другом значении будет вы- имеет значение 0. При любом другом значении будет вы- значение 0. При любом другом значении будет вы- значение 0. При любом другом значении будет вы- 0. При любом другом значении будет вы- При любом другом значении будет вы- полняться циклическое переименование последовательности filename.1, filename.2 , ..., filename.N, где filename.1 всегда представляет последнюю ре- зервную копию, а filename.N – всегда самую старую. Режим mode определяет режим открытия файла журнала. По умолчанию аргумент mode имеет зна- имеет зна- зна- зна- чение ‘a’. Если в аргументе maxBytes передается значение 0 (по умолчанию), резервные копии файла журнала не создаются и размер его никак не будет ограничиваться. Аргументы encoding и delay имеют тот же смысл, что и в обработчике FileHandler. handlers.SMTPHandler(mailhost, fromaddr, toaddrs, subject [, credentials]) Отправляет сообщение по электронной почте. В аргументе mailhost пере- дается адрес сервера SMTP, который сможет принять сообщение. Адрес может быть простым именем хоста, указанным в виде строки, или корте- жем (host, port). В аргументе fromaddr передается адрес отправителя, в ар- гументе toaddrs – адрес получателя и в аргументе subject – тема сообщения. В аргументе credentials передается кортеж (username, password) с именем пользователя и паролем. handlers.SocketHandler(host, port) Отправляет сообщение удаленному хосту по протоколу TCP. Аргументы host и port определяют адрес получателя. Сообщения отправляются в том же виде, в каком их отправляет обработчик DatagramHandler. В отличие от Data- gramHandler , этот обработчик обеспечивает надежную доставку сообщений. 456 Глава 19. Службы операционной системы StreamHandler([fileobj]) Выводит сообщение в уже открытый объект файла fileobj. При вызове без аргумента сообщение выводится в поток sys.stderr. handlers.SysLogHandler([address [, facility]]) Передает сообщение демону системного журнала в системе UNIX. В аргу- UNIX. В аргу- . В аргу- менте address передается адрес хоста назначения в виде (host, port). Если этот аргумент опущен, используется адрес (‘localhost’, 514). В аргументе facility передается целочисленный код типа источника сообщения; аргу- мент по умолчанию принимает значение SysLogHandler.LOG_USER. Полный список кодов источников сообщений можно найти в определении обработ- чика SysLogHandler. handlers.TimedRotatingFileHandler(filename [, when [, interval [, backupCount [, encoding [, delay [, utc]]]]]]) То же, что и RotatingFileHandler, но циклическое переименование файлов происходит через определенные интервалы времени, а не по достижении файлом заданного размера. В аргументе interval передается число, опреде- ляющее величину интервала в единицах, а в аргументе when – строка, опре- деляющая единицы измерения. Допустимыми значениями для аргумента when являются: ‘S’ (секунды), ‘M’ (минуты), ‘H’ (часы), ‘D’ (дни), ‘W’ (недели) и ‘midnight’ (ротация выполняется в полночь). Например, если в аргументе interval передать число 3, а в аргументе when – строку ‘D’, ротация файла журнала будет выполняться каждые три дня. Аргумент backupCount опреде- опреде- ляет максимальное число хранимых резервных копий. В аргументе utc пе- редается логический флаг, который определяет, должно ли использоваться локальное время (по умолчанию) или время по Гринвичу (UTC). handlers.WatchedFileHandler(filename [, mode [, encoding [, delay]]]) То же, что и FileHandler, но следит за индексным узлом (inode) и устрой- inode) и устрой- ) и устрой- ством открытого файла журнала. Если с момента записи последнего со- общения они изменились, файл закрывается и открывается снова под тем же именем filename. Эти изменения могут быть вызваны удалением файла журнала или его переименованием в процессе выполнения операции ро- тации, произведенной внешней программой. Этот обработчик действует только в системах UNIX. Настройка обработчиков Каждому объекту h класса Handler может быть присвоен собственный уро- вень важности и фильтры. Для этого используются следующие методы: h.setLevel(level) Устанавливает порог важности обрабатываемых значений. В аргументе level передается числовое значение уровня, такое как ERROR или CRITICAL. h.addFilter(filt) Добавляет в обработчик объект filt класса Filter. Дополнительную инфор- мацию можно найти в описании метода addFilter() объектов класса Logger. Модуль logging 457 h.removeFilter(filt) У даляет из обработчика объект filt класса Filter. Важно отметить, что уровни важности и фильтры могут устанавливаться в обработчиках независимо от объектов класса Logger, к которым подклю- чаются обработчики. Эту особенность иллюстрирует следующий пример: import logging import sys ёё # Создать обработчик, который выводит сообщения с уровнем CRITICAL # в поток stderr crit_hand = logging.StreamHandler(sys.stderr) crit_hand.setLevel(logging.CRITICAL) ёё # Создать регистратор верхнего уровня с именем ‘app’ app_log = logging.getLogger(“app”) app_log.setLevel(logging.INFO) app_log.addHandler(logging.FileHandler(‘app.log’)) app_log.addHandler(crit_handler) В этом примере создается единственный регистратор с именем ‘app’ и уров- нем INFO. К нему подключаются два обработчика, но для одного из них (crit_handler) определен свой уровень важности CRITICAL. Хотя этот обра- ботчик будет получать сообщения с уровнем важности INFO и выше, тем не менее он будет игнорировать сообщения, уровень которых ниже CRITICAL. Очистка обработчиков Следующие методы используются для выполнения завершающих опера- ций при работе с обработчиками. h.flush() Выталкивает все внутренние буферы обработчика. h.close() Закрывает обработчик. Форматирование сообщений По умолчанию объекты класса Handler выводят сообщения в том виде, в ка- ком они передаются функциям модуля logging. Однако иногда бывает не- обходимо добавить в сообщение дополнительную информацию, например время, имя файла, номер строки и так далее. В этом разделе рассказывает- ся, как можно реализовать автоматическое добавление этой информации в сообщения. Объекты форматирования Прежде чем изменить формат сообщения, необходимо создать объект клас- са Formatter: 458 Глава 19. Службы операционной системы Formatter([fmt [, datefmt]]) Создает новый объект класса Formatter. В аргументе fmt передается строка формата сообщения. В строке fmt допускается использовать любые симво- лы подстановки, перечисленные в описании функции basicConfig(). В аргу- менте datefmt передается строка форматирования дат в виде, совместимом с функцией time.strftime(). Если этот аргумент опущен, форматирование дат осуществляется в соответствии со стандартом ISO8601. Чтобы задействовать объект класса Formatter, его необходимо подключить к обработчику. Делается это с помощью метода h.setFormatter() экземпляра h класса Handler. h.setFormatter(format) Подключает объект форматирования, который будет использоваться эк- земпляром h класса Handler при создании сообщений. В аргументе format должен передаваться объект класса Formatter. Следующий пример иллюстрирует, как выполняется настройка формати- рования сообщений в обработчике: import logging import sys ёё # Определить формат сообщений format = logging.Formatter(“%(levelname)-10s %(asctime)s %(message)s”) ёё # Создать обработчик, который выводит сообщения с уровнем CRITICAL # в поток stderr crit_hand = logging.StreamHandler(sys.stderr) crit_hand.setLevel(logging.CRITICAL) crit_hand.setFormatter(format) В этом примере нестандартный объект форматирования подключается к обработчику crit_hand. Если этому обработчику передать сообщение, та- кое как “Creeping death detected.”, он выведет следующий текст: CRITICAL 2005-10-25 20:46:57,126 Creeping death detected. Добавление в сообщения дополнительной контекстной информации В некоторых случаях бывает полезно добавлять в журналируемые сообще- ния дополнительную контекстную информацию. Эта информация может быть получена одним из двух способов. Во-первых, все основные операции журналирования (такие как log.critical(), log.warning() и другие) принима- ют именованный аргумент extra, в котором можно передать словарь с до- полнительными полями для использования в строках формата. Эти поля объединяются с контекстными данными объектов Formatter. Например: import logging, socket logging.basicConfig( format = “%(hostname)s %(levelname)-10s %(asctime)s %(message)s” ) ёё Модуль logging 459 # Дополнительные контекстные данные netinfo = { ‘hostname’ : socket.gethostname(), ‘ip’ : socket.gethostbyname(socket.gethostname()) } log = logging.getLogger(‘app’) ёё # Вывести сообщение с дополнительными контекстными данными log.critical(“Could not connect to server”, extra=netinfo) Не достатком такого подхода является необходимость передавать дополни- тельную информацию каждой операции журналирования, в противном случае программа будет завершаться аварийно. Другой подход основан на использовании класса LogAdapter в качестве обертки для существующего регистратора. |