Анализ и использование модуля ведения журнала Python-2

Python

Небольшое резюмеВо-вторых, уровень журнала объекта Logger3. Используйте несколько процессоров и несколько форматовВ-четвертых, откат журнала1. RotatingFileHandler2. TimedRotatingFileHandler5. Проблемы с RotatingHandler

В качестве дополнения к модулю журнала Python эта статья в основном знакомит с откатом журнала.RotatingFileHandlerиTimedRotatingFileHandlerиспользование и проблемы, которые оно приносит,LoggerКак работает уровень журнала объекта и т. д.

Небольшое резюме

Через предыдущее введениеloggingсообщение в блоге модуля[Python] - подробное использование ведения журнала модуля ведения журнала - столбец ling620 - Блог CSDN, который в основном корректно работает с модулем логирования. Несколько моментов, на которые следует обратить внимание:

  1. Использовать напрямуюloggingФункция интерфейса модуля, без каких-либо других операций, таких какlogging.info()Выходные данные для ведения журнала являются выходными данными по умолчанию дляконсоль, уровень журнала по умолчаниюlogging.WARNING, и уровень ведения журнала не может быть установлен.
  2. использоватьloggingИнтерфейсная функция модуля, внутренняя реализация: оценкаroot.handlersЯвляется ли он пустым, если он пуст, он будет вызываться внутреннеbasicConfig()функция, созданная по умолчаниюStreamHandler.
  3. использоватьlogging.basicConfig()Функция может соответствовать основному использованию, может выводить в файл или консоль. Интерьер создается по параметрамFileHandlerилиStreamHandlerреализовать.
  4. LoggerНевозможно создать экземпляр напрямую, вам нужно использоватьlogging.getLogger()ПолучатьLoggerобъект.
  5. ОдинloggerОбъекты могут добавлять несколькоhandlerобъект, черезaddHandler()функция для добавления.
  6. каждыйhandlerобъект может иметьFormatterобъект, чтобы указать формат, черезsetFormatter()функция для установки.
  7. handlerиloggerОбъекты должны установить уровень журнала, черезsetLevel()функция для установки.
  8. loggerИмя'.'разделенная иерархия, каждая'.'Назадloggerоба'.'фронтloggerизchildren.
  9. не обязательно использовать для всехloggersопределить и настроитьhandlers, только должен быть верхний уровеньloggerнастроитьhandlers, затем создайте по мере необходимостиchild loggersдостаточно.
  10. loggerсуществует один"эффективный уровень"Понятие о том, еслиloggerявно не установленlevel, тоloggerпросто используй этоparentизlevel; если этоparentтакже явно не установленlevelпродолжать искатьparentизparentэффективныйlevelи так далее, пока не будет найдена явная настройкаlevelпредки.

Во-вторых, уровень журнала объекта Logger

Из вышеизложенного известно,LoggerНевозможно создать экземпляр напрямую, вам нужно использоватьlogging.getLogger(name)получитьLoggerОбъект. пройти черезsetLevel()установить уровень журнала.

В ходе тестирования были обнаружены следующие проблемы, и был установлен уровень логированияlogging.DEBUG, выводLoggerобъектlevelсвойства, результат10, но до сих пор нет выходаDEBUGУровень информации, зачем это? следующее:

 1>>> import logging
2
3>>> logger = logging.getLogger('example')
4>>> logger.level
50
6>>> logger.debug('this is a debug msg.')# 无输出
7>>> logger.warning('this is a warning msg.')
8this is a warning msg.
9>>> logger.setLevel(logging.DEBUG)
10>>> logger.level
1110
12>>> logger.debug('this is a debug msg.') # 无输出
13>>> logger.warning('this is a warning msg.')
14this is a warning msg.

Почему установлен уровень лога, а он не работает? -_-
Сначала проанализируйте приведенный выше код.LoggerОбъектlogger, но ничего не добавляетhandlerобъект. когдаlogging.getLogger()что ты сделал? Что делают функции интерфейса?

 1def getLogger(name=None):
2    """
3    Return a logger with the specified name, creating it if necessary.
4    If no name is specified, return the root logger.
5    """
6    if name:
7        return Logger.manager.getLogger(name)
8    else:
9        return root # 若未指定name,则返回root
10
11# root是什么?
12root = RootLogger(WARNING) # RootLogger的对象,日志等级为WARNING
13Logger.root = root
14Logger.manager = Manager(Logger.root)

getLogger()Внутри функции в зависимости от того, указано ли оноnameвернуть соответствующийroot logger. которыйLoggerобъект инициализации,handler,filterпараметры и т.д.None. Видно, что уровень журнала по умолчаниюWARNING.

отlogger.info()Возьмем для примера интерфейсную функцию, посмотрим, что сделано?

Связь вызова функции:

接口函数调用关系
Связь вызова функции интерфейса

под анализомLogger.callHandlers()функция:

1def callHandlers(self, record):
2    if (found == 0):
3        if lastResort:
4            if record.levelno >= lastResort.level:
5                lastResort.handle(record)
6        elif raiseExceptions and not self.manager.emittedNoHandlerWarning:
7            sys.stderr.write("No handlers could be found for logger"
8                                 " \"%s\"\n" % self.name)
9            self.manager.emittedNoHandlerWarning = True
  1. циклLoggerсобственный экземпляр, пока не будут получены его предки,foundсчитатьhandlers.
  2. судитьfoundЧисло, если оно равно 0, оценитьlastResort

этоlastResortчто это? следующее:
это_StderrHandler(WARNING)Объект инициализации класса и переданный по умолчанию уровень журнала:WARNING, указать нельзя.
_StderrHandlerкласс наследуется отStreamHandler,использоватьsys.stderrпохожий наStreamHandler.

 1_defaultLastResort = _StderrHandler(WARNING) # 注意此处是WARNING
2lastResort = _defaultLastResort
3
4class _StderrHandler(StreamHandler):
5    """
6    This class is like a StreamHandler using sys.stderr, but always uses
7    whatever sys.stderr is currently set to rather than the value of
8    sys.stderr at handler construction time.
9    """
10    def __init__(self, level=NOTSET):
11        """
12        Initialize the handler.
13        """
14        Handler.__init__(self, level)
15
16    @property
17    def stream(self):
18        return sys.stderr

Я видел это здесь, причина, по которой я получаюLoggerObject, после установки уровня журнала причина, по которой он все еще не вступает в силу, заключается в том, что мы не добавили никакихhandler, вызов по умолчанию в программе указывает, что уровеньWARNINGиз_StderrHandler, и уровень журнала не может быть изменен (используяsetLevel()не влияет наhandlerкласс объекта)

когда мы вручную добавилиhandlerобъект, добавленныйhandlerкласс объекта илиroot Loggerуровень.

при звонкеlogging.basicConfig()функция, она создается по умолчанию внутриFileHandlerилиStreamHandlerобъект, то устанавливаемsetLevel()может вступить в силу. следующее:

1import loging
2logging.basicConfig(level=logging.DEBUG)
3logger = logging.getLogger()
4logger.debug('this is a debug msg.')
5# 输出
6INFO:root:this is a debug msg.

3. Используйте несколько процессоров и несколько форматов

Регистраторы — это обычные объекты Python.addHandler()методКоличество процессоров журналов, которые можно добавить, не ограничено.. Иногда приложению необходимо записывать критические сообщения в текстовый файл, а сообщения об ошибках или другие уровни — в консоль. Для этого достаточно настроить еще несколько обработчиков логирования, а вызовы логирования в коде приложения могут остаться прежними.

 1import logging
2
3logger = logging.getLogger('simple_example')
4logger.setLevel(logging.DEBUG)
5# 创建文件handler ,其等级为debug
6fh = logging.FileHandler('example.log')
7fh.setLevel(logging.DEBUG)
8# 创建控制台handler,日志等级为ERROR
9ch = logging.StreamHandler()
10ch.setLevel(logging.ERROR)
11# 创建formatter并添加至handlers
12formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
13ch.setFormatter(formatter)
14fh.setFormatter(formatter)
15# 将handlers添加至logger
16logger.addHandler(ch)
17logger.addHandler(fh)
18
19# 应用代码
20logger.debug('debug message')
21logger.info('info message')
22logger.warning('warn message')
23logger.error('error message')
24logger.critical('critical message')

Результатом приведенного выше кода является то, что консоль выводит толькоerrorиcritical, и файл содержит все 5 сообщений журнала.

В-четвертых, откат журнала

Благодаря предыдущему анализу мы можем вывести информацию журнала в файл.Со временем файл журнала будет становиться все больше и больше.Как поступить в этой ситуации?

Мы хотим открыть новый файл и записать, когда файл журнала продолжает увеличиваться до определенного размера или в течение определенного периода времени. Вы можете захотеть сохранить только определенное количество файлов журналов, и когда количество файлов создается постоянно, первый файл будет перезаписан, чтобы сформировать цикл. Для этого варианта использования пакет ведения журнала предоставляетlogging.hanlders.RotatingFileHandlerиlogging.hanlders.TimedRotatingFileHandler.

Как упоминалось в предыдущей статье:

своего рода описывать
logging.handlers.RotatingFileHandler Отправлять сообщения журнала нафайл на дискеи поддерживает файлы журналовобрезать по размеру
logging.hanlders.TimedRotatingFileHandler Отправлять сообщения журнала нафайл на дискеи поддерживает файлы журналовсократить по времени

1. RotatingFileHandler

По умолчанию файл растет бесконечно. можно указатьmaxBytesиbackupCountконкретное значение, позволяющее прокручивать файл до заданного размера.

Когда длина текущего файла журнала близка кmaxBytes, происходит опрокидывание. еслиbackupCount为>= 1, система будет постоянно создавать новые файлы с тем же путем, что и у базового файла, но с расширением".1",".2"прикреплен к нему.

Например, еслиbackupCountза5, а базовый файл называется“app.log”, ты получишь“app.log”,“app.log.1”,“app.log.2”,…,“app.log.5”.

Файл, в который записывается, всегда“app.log”

Когда он был заполнен, он был закрыт и переименован в“app.log.1”, если файл“app.log.1”,“app.log.2”и т. д. существуют, затем переименуйте их в“app.log.2”,“app.log.3”Ждать.

  • еслиmaxBytesноль, опрокидывание не произойдет.
  • Если вы хотите перевернуть функцию, тоmode='a'.

Определение функции инициализации:

1__init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False)

Параметры инициализации:

имя параметра значение
filename имя файла
mode файловый режим. При использовании функции отката установите значениеa
maxBytes размер файла, максимальное количество битов, например1024*1024*1024означаетG
backupCount Количество откатов файлов, если установлено3, он будет хранить 3 файла резервных копий, всего 4 файла журнала
encoding Формат кодировки файла, если он содержит китайский язык, используйтеutf-8кодирование
delay ПостроитьHandler, используется для установки уровня, формата и т. д. еслиTrue,ПостроитьHandlerобъект, иначе построитьStreamHandlerобъект. дефолтFalse

2. TimedRotatingFileHandler

параметрwhenОпределяет тип временного интервала, параметрintervalОпределяет количество временных интервалов. какwhen=‘D’,interval=2, который относится к интервалу времени в два дня,backupCountРешил вести несколько лог-файлов. При превышении этого числа старые файлы журналов будут удалены.

Определение функции инициализации

1__init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None)

Параметры инициализации:

имя параметра значение
filename имя файла
when тип временного интервала
interval временной интервал,
backupCount Количество откатов файлов, если установлено3, он будет хранить 3 файла резервных копий, всего 4 файла журнала
encoding Формат кодировки файла, если он содержит китайский язык, используйтеutf-8кодирование
delay ПостроитьHandler, используется для установки уровня, формата и т. д. еслиTrue,ПостроитьHandlerобъект, иначе построитьStreamHandlerобъект. дефолтFalse
utc время в часовом поясе UTC

параметрwhen:

символ значение
S второй
M минута
H Час
D небо
W неделю
W0-W6 с понедельника по воскресенье
midnight в полночь, каждое утро

Пример:

 1import glob
2import logging
3import logging.handlers
4
5my_logger = logging.getLogger('MyLogger')
6my_logger.setLevel(logging.DEBUG)
7
8# Add the log message handler to the logger
9handler = logging.handlers.RotatingFileHandler(
10              'logs/logging_demo.log', maxBytes=1024*1024, backupCount=5)
11
12my_logger.addHandler(handler)

Полученные файлы журнала выглядят следующим образом, всего 6 файлов:

1logging_demo.log
2logging_demo.log.1
3logging_demo.log.2
4logging_demo.log.3
5logging_demo.log.4
6logging_demo.log.5

5. Проблемы с RotatingHandler

питонloggingМодуль обеспечивает два отката журнала, которые поддерживаютFileHandlerклассы, которыеRotatingFileHandlerиTimedRotatingFileHandler.

loggingЯвляется потокобезопасным, без проблем регистрирует несколько потоков в одном процессе в один файл. Но когда несколько процессов записывают журналы в один и тот же файл журнала, эти дваRotatingHandlerЭто принесет проблемы, такие как потеря журнала.

В этой части рассматривается метод ведения журнала из нескольких процессов в один файл, см. следующую статью:

Многопроцессное ведение журнала Python Develop Paper