Небольшое резюмеВо-вторых, уровень журнала объекта Logger3. Используйте несколько процессоров и несколько форматовВ-четвертых, откат журнала1. RotatingFileHandler2. TimedRotatingFileHandler5. Проблемы с RotatingHandler
В качестве дополнения к модулю журнала Python эта статья в основном знакомит с откатом журнала.
RotatingFileHandlerиTimedRotatingFileHandlerиспользование и проблемы, которые оно приносит,LoggerКак работает уровень журнала объекта и т. д.
Небольшое резюме
Через предыдущее введениеloggingсообщение в блоге модуля[Python] - подробное использование ведения журнала модуля ведения журнала - столбец ling620 - Блог CSDN, который в основном корректно работает с модулем логирования. Несколько моментов, на которые следует обратить внимание:
- Использовать напрямую
loggingФункция интерфейса модуля, без каких-либо других операций, таких какlogging.info()Выходные данные для ведения журнала являются выходными данными по умолчанию дляконсоль, уровень журнала по умолчаниюlogging.WARNING, и уровень ведения журнала не может быть установлен. - использовать
loggingИнтерфейсная функция модуля, внутренняя реализация: оценкаroot.handlersЯвляется ли он пустым, если он пуст, он будет вызываться внутреннеbasicConfig()функция, созданная по умолчаниюStreamHandler. - использовать
logging.basicConfig()Функция может соответствовать основному использованию, может выводить в файл или консоль. Интерьер создается по параметрамFileHandlerилиStreamHandlerреализовать. -
LoggerНевозможно создать экземпляр напрямую, вам нужно использоватьlogging.getLogger()ПолучатьLoggerобъект. - Один
loggerОбъекты могут добавлять несколькоhandlerобъект, черезaddHandler()функция для добавления. - каждый
handlerобъект может иметьFormatterобъект, чтобы указать формат, черезsetFormatter()функция для установки. -
handlerиloggerОбъекты должны установить уровень журнала, черезsetLevel()функция для установки. -
loggerИмя'.'разделенная иерархия, каждая'.'Назадloggerоба'.'фронтloggerизchildren. - не обязательно использовать для всех
loggersопределить и настроитьhandlers, только должен быть верхний уровеньloggerнастроитьhandlers, затем создайте по мере необходимостиchild loggersдостаточно. -
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
- цикл
Loggerсобственный экземпляр, пока не будут получены его предки,foundсчитатьhandlers. - судить
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Это принесет проблемы, такие как потеря журнала.
В этой части рассматривается метод ведения журнала из нескольких процессов в один файл, см. следующую статью: