Небольшое резюмеВо-вторых, уровень журнала объекта 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
Я видел это здесь, причина, по которой я получаюLogger
Object, после установки уровня журнала причина, по которой он все еще не вступает в силу, заключается в том, что мы не добавили никаких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
Это принесет проблемы, такие как потеря журнала.
В этой части рассматривается метод ведения журнала из нескольких процессов в один файл, см. следующую статью: