справочник по Python. мм isbn 9785932861578 9 785932 861578
Скачать 4.21 Mb.
|
LogAdapter(log [, extra]) Создает обертку вокруг объекта log класса Logger. В аргументе extra пере- дается словарь с дополнительной контекстной информацией, которая пе- редается объекту форматирования. Экземпляры класса LogAdapter имеют тот же интерфейс, что и объекты класса Logger. Однако методы, которым передаются сообщения, автоматически будут добавлять дополнительную информацию, полученную в аргументе extra. Следующий пример демонстрирует использование объекта LogAdapter: import logging, socket logging.basicConfig( format = “%(hostname)s %(levelname)-10s %(asctime)s %(message)s” ) ёё # Дополнительные контекстные данные netinfo = { ‘hostname’ : socket.gethostname(), ‘ip’ : socket.gethostbyname(socket.gethostname()) } ёё # Создать регистратор log = logging.LogAdapter(logging.getLogger(“app”), netinfo) ёё # Вывести сообщение. # Дополнительные контекстные данные поставляются объектом LogAdapter log.critical(“Could not connect to server”) Различные вспомогательные функции Следующие функции из модуля logging управляют различными параме- трами журналирования: disable(level) На глобальном уровне запрещает вывод сообщений с уровнем важности ниже значения level. Эта функция может использоваться для отключения журналирования для всего приложения, например, если временно нужно запретить вывод или уменьшить поток журналируемых сообщений. 460 Глава 19. Службы операционной системы addLevelName(level, levelName) Создает новый уровень важности с указанным именем. В аргументе level передается числовое значение, а в аргументе levelName – строка. Может ис- пользоваться для изменения имен встроенных уровней или для добавле- ния новых уровней, вдобавок к поддерживаемым по умолчанию. getLevelName(level) Возвращает имя уровня, соответствующего числовому значению level. shutdown() Уничтожает все объекты регистраторов, предварительно выталкивает бу- феры, если необходимо. Настройка механизма журналирования Настройка приложения на использование модуля logging обычно выполня- ется в несколько основных этапов: 1. С помощью функции getLogger() создается несколько объектов класса Logger . Соответствующим образом устанавливаются значения параме- тров, таких как уровень важности. 2. Создаются объекты обработчиков различных типов (таких как FileHan- dler , StreamHandler, SocketHandler и так далее) и устанавливаются соответ- ствующие уровни важности. 3. Создаются объекты класса Formatter и подключаются к объектам Han- dler с помощью метода setFormatter(). 4. С помощью метода addHandler() объекты Handler подключаются к объек- там Logger. Каждый этап может оказаться достаточно сложным, поэтому лучше всего поместить реализацию настройки механизма журналирования в одном, хорошо документированном, месте. Например, можно создать файл applog- config.py , который будет импортироваться основным модулем приложения: # applogconfig.py 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) ёё # Создать обработчик, который выводит сообщения в файл applog_hand = logging.FileHandler(‘app.log’) applog_hand.setFormatter(format) ёё # Создать регистратор верхнего уровня с именем ‘app’ app_log = logging.getLogger(“app”) Модуль logging 461 app_log.setLevel(logging.INFO) app_log.addHandler(applog_hand) app_log.addHandler(crit_hand) ёё # Изменить уровень важности для регистратора ‘app.net’ logging.getLogger(“app.net”).setLevel(logging.ERROR) Е сли в какой-либо части процедуры настройки потребуется что-то изме- нить, легче будет учесть все нюансы, если вся процедура будет реализована в одном месте. Имейте в виду, что этот специальный файл должен импор- тироваться только один раз и только в одном месте программы. В других модулях программы, где потребуется выводить журналируемые сообще- ния, достаточно просто добавить следующие строки: import logging app_log = logging.getLogger(“app”) ... app_log.critical(“An error occurred”) Подмодуль logging.config Помимо жесткого определения настроек механизма журналирования в про- граммном коде на языке Python имеется также возможность реализовать настройку модуля logging в виде файла с настройками в формате INI. Для этого используются следующие функции из модуля logging.config. fileConfig(filename [, defaults [, disable_existing_loggers]]) Читает настройки механизма журналирования из файла с именем file- name . В аргументе defaults передается словарь со значениями параметров по умолчанию для использования в файле с настройками. Содержимое файла filename читается с помощью модуля ConfigParser. В аргументе disable_ex- _ex- ex- isting_loggers передается логический флаг, который определяет, должны ли отключаться существующие регистраторы после чтения новых параме- тров настройки. По умолчанию имеет значение True. Дополнительную информацию, касающуюся ожидаемого формата файлов с настройками, можно найти в электронной документации к модулю log- ging . Однако опытные программисты наверняка смогут понять основные принципы из следующего примера, который является версией файла с на- стройками, аналогичными тем, что выполнялись в примере модуля applog- config.py выше. ; applogconfig.ini ; ; Файл с настройками модуля logging ; В следующих разделах определяются имена для объектов Logger, Handler ; и Formatter, которые настраиваются ниже. [loggers] keys=root,app,app_net ёё [handlers] keys=crit,applog ёё [formatters] 462 Глава 19. Службы операционной системы keys=format ёё [logger_root] level=NOTSET handlers= ёё [logger_app] level=INFO propagate=0 qualname=app handlers=crit,applog ёё [logger_app_net] level=ERROR propagate=1 qualname=app.net handlers= ёё [handler_crit] class=StreamHandler level=CRITICAL formatter=format args=(sys.stderr,) ёё [handler_applog] class=FileHandler level=NOTSET formatter=format args=(‘app.log’,) ёё [formatter_format] format=%(levelname)-10s %(asctime)s %(message)s datefmt= Для чтения содержимого этого файла и настройки механизма журналиро- вания можно использовать следующий фрагмент программного кода: import logging.config logging.config.fileConfig(‘applogconfig.ini’) Как и ранее, нет никакой необходимости беспокоиться о настройке меха- низма журналирования в модулях, где потребуется выводить журналиру- емые сообщения. В них достаточно просто импортировать модуль logging и получить ссылку на соответствующий объект Logger. Например: import logging app_log = logging.getLogger(“app”) ... app_log.critical(“An error occurred”) Вопросы производительности Добавление в приложение механизма журналирования может существен- но ухудшить его производительность, если не отнестись к этому с долж- ным вниманием. Однако существуют некоторые приемы, которые могут помочь уменьшить это отрицательное влияние. Модуль mmap 463 Во-первых, при компиляции в оптимизированном режиме (-O) удаляется весь программный код, который выполняется в условных инструкциях, таких как if __debug__: инструкции. Если отладка – единственная цель ис- пользования модуля logging, можно поместить все вызовы механизма жур- налирования в условные инструкции, которые автоматически будут уда- ляться при компиляции в оптимизированном режиме. Второй прием заключается в использовании «пустого» объекта Null вместо объектов Logger, когда журналирование должно быть полностью отключе- но. Этот прием отличается от использования None тем, что основан на ис- пользовании объектов, которые просто пропускают все обращения к ним. Например: class Null(object): def __init__(self, *args, **kwargs): pass def __call__(self, *args, **kwargs): return self def __getattribute__(self, name): return self def __setattr__(self, name, value): pass def __delattr__(self,name): pass ёё log = Null() log.critical(“An error occurred.”) # Ничего не делает При должном уровне подготовленности журналированием можно также управлять с помощью декораторов и метаклассов. Поскольку эти две осо- бенности потребляют время только на этапе, когда Python интерпретирует определения функций, методов и классов, они позволяют добавлять и уда- лять поддержку журналирования в различных частях программы и изба- виться от потери производительности, когда журналирование выключено. Дополнительная информация по этой теме приводится в главе 6 «Функции и функциональное программирование» и в главе 7 «Классы и объектно- ориентированное программирование». Примечания • Модуль logging имеет множество параметров настройки, которые не об- суждались здесь. За дополнительными подробностями читателям сле- дует обращаться к электронной документации. • Модуль logging может использоваться в многопоточных программах. В частности, нет никакой необходимости окружать операциями блоки- ровки программный код, который выводит журналируемые сообщения. Модуль mmap Модуль mmap обеспечивает поддержку объектов отображений файлов в па- мяти. Эти объекты ведут себя, как обычные файлы и строки байтов, и в большинстве случаев могут использоваться вместо обычных файлов и строк байтов. Кроме того, содержимое отображений файлов в памяти яв- ляется изменяемым. Это означает, что любые изменения могут быть вы- полнены с помощью операций индексирования и получения срезов. Если 464 Глава 19. Службы операционной системы отображение файла не было сделано частным, такие изменения напрямую будут отражаться на содержимом самого файла. Отображение файла в памяти создается с помощью функции mmap(), кото- рая немного отличается в версиях для UNIX и Windows. mmap(fileno, length [, flags, [prot [,access [, offset]]]]) (UNIX). Возвращает объект mmap и отображает length байтов из файла, определяемого целочисленным дескриптором fileno. Если в аргументе fileno передать значение -1, будет создано анонимное отображение памяти. Аргумент flags определяет природу отображения и может принимать одно из следующих значений: Флаг Описание MAP_PRIVATE Создает частную копию отображения. Изменения в объекте будут наблюдаться только в данном процессе. MAP_SHARED Создает отображение, которое может совместно использоваться всеми процессами, которые отображают одну и ту же область файла. Изменения в объекте будут оказывать влияние на все отображения. По умолчанию аргумент flags имеет значение MAP_SHARED. Аргумент prot опре- деляет уровень защиты памяти объекта и представляет собой битовую ма- ску, составленную из следующих флагов с помощью битовой операции ИЛИ: Флаг Описание PROT_READ Данные в объекте доступны для чтения. PROT_WRITE Объект позволяет изменять содержимое. PROT_EXEC Объект может содержать выполняемые инструкции. По умолчанию аргумент prot получает значение PROT_READ | PROT_WRITE. Фла- ги, указанные в аргументе prot, должны соответствовать режиму открытия дескриптора файла fileno. В большинстве случаев это означает, что файл должен быть открыт для чтения/записи (например, os.open(name, os.O_RDWR)). Необязательный аргумент access может использоваться в качестве альтер- нативы аргументам flags и prot. Этот аргумент может принимать одно из следующих значений: Права доступа Описание ACCESS_READ Объект доступен только для чтения. ACCESS_WRITE Объект доступен для чтения/записи со сквозной записью. Изменения немедленно записываются в сам файл. ACCESS_COPY Объект доступен для чтения/записи с копированием при запи- си. Изменения могут выполняться в памяти, но они не записы- ваются в сам файл. Модуль mmap 465 Обычно аргумент access передается в виде именованного аргумента, на- пример mmap(fileno, length, access=ACCESS_READ). Одновременная передача аргументов access и flags считается ошибкой. Аргумент offset определяет смещение отображаемой области в байтах относительно начала файла и по умолчанию принимает значение 0. Это значение должно быть кратным значению mmap.ALLOCATIONGRANULARITY. mmap(fileno, length[, tagname [, access [, offset]]]) (Windows) Возвращает объект mmap и отображает length байтов из файла, определяемого целочисленным дескриптором fileno. Если в аргументе fileno передать значение -1, будет создано анонимное отображение памя- ти. Если в аргументе length передать значение, которое превышает размер файла, файл будет увеличен до размера length. Если в аргументе length передать значение 0, то при создании отображения будет использоваться текущая длина файла, если файл не пустой (в противном случае будет воз- буждено исключение). В необязательном аргументе tagname можно передать строку, которую можно будет использовать в качестве имени отображения. Если в аргументе tagname передать имя существующего отображения, бу- дет открыто это отображение. В противном случае будет создано новое ото- бражение. Если в аргументе tagname передать значение None, будет создано не именованное отображение. Необязательный аргумент access определяет режим доступа. Он может принимать те же значения, что были перечис- доступа. Он может принимать те же значения, что были перечис- доступа. Он может принимать те же значения, что были перечис- . Он может принимать те же значения, что были перечис- Он может принимать те же значения, что были перечис- лены выше, в описании версии mmap() для UNIX. По умолчанию аргумент access принимает значение ACCESS_WRITE. Аргумент offset определяет сме- щение отображаемой области в байтах относительно начала файла и по умолчанию принимает значение 0. Это значение должно быть кратным значению mmap.ALLOCATIONGRANULARITY. Объект m отображения файла в памяти поддерживает следующие методы. m.close() Закрывает файл. Последующие попытки выполнить какие-либо операции будут вызывать исключение. m.find(string[, start]) Возвращает индекс первого вхождения строки string. Необязательный ар- Необязательный ар- гумент start определяет позицию начала поиска. Возвращает -1, если ис- комая строка не была найдена. m.flush([offset, size]) Записывает изменения, выполненные в памяти, обратно в файл. Аргумен- ты offset и size определяют диапазон участка памяти, который должен быть записан. В противном случае выполняется запись всего отображения. m.move(dst,src,count) Копирует count байтов, начиная с позиции src, в позицию dst. Копирование выполняется с помощью функции memmove() языка C, которая гарантирует корректную работу, когда исходная и конечная области копирования пере- крываются. 466 Глава 19. Службы операционной системы m.read(n) Читает до n байтов, начиная с текущей позиции в файле, и возвращает дан- ные в виде строки. m.read_byte() Читает единственный байт, начиная с текущей позиции в файле, и возвра- щает данные в виде строки длины 1. m.readline() Возвращает строку текста, начиная с текущей позиции в файле. m.resize(newsize) Изменяет размер объекта отображаемой памяти до нового размера newsize в байтах. m.seek(pos[, whence]) Изменяет местоположение текущей позиции в файле. Аргументы pos и whence имеют тот же смысл, что и в методе seek() объектов файлов. m.size() Возвращает длину файла. Это значение может быть больше, чем размер отображаемой области. m.tell() Возвращает значение текущей позиции в файле. m.write(string) Записывает строку байтов в файл, начиная с текущей позиции. m.write_byte(byte) Записывает единственный байт в память, в текущую позицию. Примечания • Несмотря на то что для UNIX и Windows предоставляются немного от- UNIX и Windows предоставляются немного от- и Windows предоставляются немного от- Windows предоставляются немного от- предоставляются немного от- личающиеся версии функции mmap(), тем не менее этот модуль позволя- ет писать переносимый программный код, опирающийся на необяза- тельный аргумент access, который является общим для обеих версий функции. Например, вызов mmap(fileno,length,access=ACCESS_WRITE) будет работать как в UNIX, так и в Windows. • Некоторые отображения в память можно создать, только если их длина кратна размеру страницы памяти в системе, который хранится в виде константы mmap.PAGESIZE. • В системах UNIX SVR4 анонимное отображение в память можно полу- UNIX SVR4 анонимное отображение в память можно полу- SVR4 анонимное отображение в память можно полу- SVR4 анонимное отображение в память можно полу- 4 анонимное отображение в память можно полу- чить вызовом mmap() для файла /dev/zero, открытого с соответствующи- ми разрешениями. • В системах UNIX BSD анонимное отображение в память можно полу- UNIX BSD анонимное отображение в память можно полу- BSD анонимное отображение в память можно полу- BSD анонимное отображение в память можно полу- анонимное отображение в память можно полу- чить вызовом mmap() с отрицательным дескриптором файла и флагом mmap.MAP_ANON |