Обзор журнала
Обзор журнала энциклопедии Baidu:
Сетевые операционные системы Windows разработаны с различными файлами журналов, такими как журналы приложений, журналы безопасности, системные журналы, журналы службы планировщика, журналы FTP, журналы WWW, журналы DNS-сервера и т. д. Эти службы включаются в зависимости от вашей системы. Когда мы выполняем какие-либо операции в системе, эти файлы журналов обычно записывают некоторое связанное с ними содержимое наших операций, что весьма полезно для сотрудников системной безопасности. Например, если кто-то выполняет обнаружение IPC в системе, система быстро запишет в журнал безопасности IP-адрес, время, имя пользователя и т. д., используемые детектором. имя пользователя, используемое для зонда, и т. д.
логи в моем образе:
Просмотр журнала — лучший способ для разработчиков ежедневно получать информацию, устранять неполадки и обнаруживать проблемы.Записи журнала обычно помечаются такой информацией, как причина исключения, время возникновения и количество строк ошибок, что значительно экономит время нашего исследования, практически повышая эффективность кодирования.
классификация бревен
Мы можем классифицировать по выходному терминалу или по уровню журнала. Терминал вывода относится к отображению журнала на консоли и сохранению журнала в файле; уровень журнала относится к разделению уровней серьезности, таких как Отладка, Информация, ПРЕДУПРЕЖДЕНИЕ, ОШИБКА и КРИТИЧЕСКИЙ.
Ведение журнала Python
logging предоставляет набор удобных функций ведения журнала: debug(), info(), warning(), error() и Critical(). Функции регистрации названы в соответствии с уровнем или серьезностью событий, для отслеживания которых они используются. Уровни критериев и их применимость описаны ниже (в порядке возрастания серьезности):
Числовое значение, соответствующее каждому уровню, равно КРИТИЧЕСКИЙ: 50, ОШИБКА: 40, ПРЕДУПРЕЖДЕНИЕ: 30, ИНФОРМАЦИЯ: 20, ОТЛАДКА: 10, НЕУСТАНОВЛЕНО: 0. Уровень ведения журнала по умолчанию в Python — ПРЕДУПРЕЖДЕНИЕ, журналы уровней ОТЛАДКИ и ИНФОРМАЦИИ не будут отображаться, измените настройку в ведении журнала.
вывод журнала
вывод на консоль
Используйте ведение журнала для печати журналов в консоли, здесь мы используем редактор Pycharm для наблюдения:
import logging
logging.debug('崔庆才丨静觅、韦世东丨奎因')
logging.warning('邀请你关注微信公众号【进击的 Coder】')
logging.info('和大佬一起coding、共同进步')
Судя по результатам выполнения приведенного выше рисунка, верно, что отображается только информация уровня ПРЕДУПРЕЖДЕНИЕ, что подтверждает вышеуказанную точку зрения. В то же время содержимое журнала также выводится на консоль.По умолчанию функции модуля ведения журнала используются в Python для печати журнала.Журнал будет выводиться только на консоль и не будет сохраняться в ежедневном журнале. файл.
Есть ли способ изменить уровень журнала по умолчанию?
Конечно, есть. BasicConfig предоставляется в журнале, чтобы пользователи могли своевременно настроить уровень журнала по умолчанию. Мы можем изменить приведенный выше код на:
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug('崔庆才丨静觅、韦世东丨奎因')
logging.warning('邀请你关注微信公众号【进击的 Coder】')
logging.info('和大佬一起coding、共同进步')
Вы можете установить уровень параметра level в basicConfig.
Учтите: если заданный уровеньlogging.INFO, можно ли отображать информацию DEBUG?
сохранить в файл
Я только что продемонстрировал, как выводить содержимое лога в консоль и свободно задавать уровень лога.Теперь давайте посмотрим, как сохранить лог в файл. По-прежнему мощный basicConfig, давайте изменим приведенный выше код на:
import logging
logging.basicConfig(level=logging.DEBUG, filename='coder.log', filemode='a')
logging.debug('崔庆才丨静觅、韦世东丨奎因')
logging.warning('邀请你关注微信公众号【进击的 Coder】')
logging.info('和大佬一起coding、共同进步')
Заполните filename (указанное имя файла) и filemode (режим записи файла) в конфигурации, и вывод журнала консоли исчезнет, так будет ли сгенерирован coder.log?
Журнал с именем coder.log создается на том же уровне, что и файл .py.
Путем нехитрых настроек кода мы добились вывода лог-файла в консоль и в файл. Как насчет отображения его в консоли и сохранения в файл?
мощная регистрация
Функция ведения журнала на уровне модуля, предоставляемая ведением журнала, представляет собой инкапсуляцию связанных классов системы ведения журнала.
Модуль ведения журнала предоставляет два способа записи журналов:
- Используйте функции уровня модуля, предоставляемые ведением журнала
- Используйте четыре компонента системы ведения журналов
Упомянутые здесь функции уровня — это DEBGE, ERROR и другие уровни, использованные выше, а четыре компонента относятся к регистраторам компонентов, обработчикам, фильтрам и средствам форматирования.На следующем рисунке кратко поясняются их соответствующие роли:
Регистратор — это запись, а реальная работа — это обработчик.Обработчик также может фильтровать и форматировать содержимое журнала для вывода через фильтры и средства форматирования.Четыре компонента
Ниже описаны классы, относящиеся к четырем основным компонентам ведения журнала: Logger, Handler, Filter и Formatter.
Класс регистратора
Объект Logger выполняет 3 задания:
1)向应用程序代码暴露几个方法,使应用程序可以在运行时记录日志消息;
2)基于日志严重等级(默认的过滤设施)或filter对象来决定要对哪些日志进行后续处理;
3)将日志消息传送给所有感兴趣的日志handlers。
Наиболее часто используемые методы объектов Logger делятся на две категории: методы настройки и методы отправки сообщений.
Наиболее распространенные методы настройки следующие:
Примечание о методе Logger.setLevel():
Среди встроенных уровней самый низкий уровень — DEBUG, а самый высокий — CRITICAL. Например установить уровень(logging.INFO), параметр функции - INFO, то логгер будет обрабатывать только логи уровней INFO, WARNING, ERROR и CRITICAL, а сообщения уровня DEBUG будут игнорироваться/отбрасываться.
После настройки объекта регистратора вы можете использовать следующие методы для создания записей журнала:
Итак, как получить объект Logger? Один из способов — создать экземпляр класса Logger с помощью метода инстанцирования класса Logger, но мы обычно используем второй способ — метод logging.getLogger().Метод logging.getLogger() имеет необязательный параметр name, который указывает имя возвращаемого логгера.Если этот параметр не указан, его значение равно 'root'. Многократный вызов метода getLogger() с одним и тем же значением параметра name вернет ссылку на один и тот же объект регистратора.
关于logger的层级结构与有效等级的说明:
logger的名称是一个以'.'分割的层级结构,每个'.'后面的logger都是'.'前面的logger的children,例如,有一个名称为 foo 的logger,其它名称分别为 foo.bar, foo.bar.baz 和 foo.bam都是 foo 的后代。
logger有一个"有效等级(effective level)"的概念。如果一个logger上没有被明确设置一个level,那么该logger就是使用它parent的level;如果它的parent也没有明确设置level则继续向上查找parent的parent的有效level,依次类推,直到找到个一个明确设置了level的祖先为止。需要说明的是,root logger总是会有一个明确的level设置(默认为 WARNING)。当决定是否去处理一个已发生的事件时,logger的有效等级将会被用来决定是否将该事件传递给该logger的handlers进行处理。
child loggers在完成对日志消息的处理后,默认会将日志消息传递给与它们的祖先loggers相关的handlers。因此,我们不必为一个应用程序中所使用的所有loggers定义和配置handlers,只需要为一个顶层的logger配置handlers,然后按照需要创建child loggers就可足够了。我们也可以通过将一个logger的propagate属性设置为False来关闭这种传递机制。
Handler
Роль объекта Handler заключается (в зависимости от уровня сообщения журнала) в распространении сообщения в место, указанное обработчиком (файл, сеть, почта и т. д.). Объект Logger может добавлять к себе 0 или более объектов-обработчиков с помощью метода addHandler(). Например, приложение может захотеть реализовать следующие требования к ведению журнала:
1)把所有日志都发送到一个日志文件中;
2)把所有严重级别大于等于error的日志发送到stdout(标准输出);
3)把所有严重级别为critical的日志发送到一个email邮件地址。
这种场景就需要3个不同的handlers,每个handler复杂发送一个特定严重级别的日志到一个特定的位置。
В обработчике очень мало методов, о которых должен заботиться разработчик приложения. Разработчикам приложений, использующим встроенный объект-обработчик, кажется, что единственными подходящими методами-обработчиками являются следующие методы конфигурации:
Чтобы было ясно, код приложения не должен напрямую создавать и использовать экземпляры Handler. Поскольку Handler является базовым классом, он определяет только интерфейс, который должен быть у всех обработчиков, и предоставляет некоторые варианты поведения по умолчанию, которые подклассы могут использовать или напрямую переопределять. Вот некоторые часто используемые обработчики:Formater
Объект Formater используется для настройки окончательного порядка, структуры и содержания сообщений журнала. В отличие от базового класса logging.Handler, код приложения может напрямую создавать экземпляр класса Formatter. Кроме того, если вашему приложению требуется особое поведение при обработке, для этого вы также можете реализовать подкласс Formatter.
Конструктор класса Formatter определяется следующим образом:
logging.Formatter.__init__(fmt=None, datefmt=None, style='%')
Конструктор принимает 3 необязательных параметра:
- fmt: указывает строку формата сообщения. Если этот параметр не указан, по умолчанию используется исходное значение сообщения.
- datefmt: укажите строку формата даты, если этот параметр не указан, по умолчанию используется "%Y-%m-%d %H:%M:%S"
- стиль: в Python 3.2 добавлен новый параметр, доступны значения '%', '{' и '$', если этот параметр не указан, по умолчанию используется '%'
Filter
Фильтр может использоваться обработчиком и регистратором для выполнения более мелких и сложных функций фильтрации, чем уровень. Фильтр — это базовый класс фильтра, который позволяет проходить фильтр только событиям журналов с определенным уровнем ведения журнала. Класс определяется следующим образом:
class logging.Filter(name='')
filter(record)
Например, если значение параметра имени, переданное при создании экземпляра фильтра, равно «A.B», то экземпляр фильтра будет разрешать только записи журнала, созданные регистраторами, чьи имена похожи на следующие правила для прохождения фильтра: «A.B». ', 'AB,C' ', 'ABCD', 'ABD', а имя 'A.BB', журналы, созданные регистраторами 'B.A.B', будут отфильтрованы. Если значением name является пустая строка, все события журнала могут проходить через фильтр.
Метод filter используется для специального контроля того, могут ли переданные записи пройти фильтрацию.Если возвращаемое значение этого метода равно 0, это означает, что фильтр не может пройти, а возвращаемое значение не равно 0, что означает, что фильтр может пройти.
说明:
如果有需要,也可以在filter(record)方法内部改变该record,比如添加、删除或修改一些属性。
我们还可以通过filter做一些统计工作,比如可以计算下被一个特殊的logger或handler所处理的record数量等。
Практическая тренировка
Так много было сказано (скопировано/вставлено) выше, пришло время попрактиковаться.
Теперь мне нужно как вывести лог на консоль, так и сохранить лог в файл, что делать?
Используя то, что мы только что узнали, мы можем представить:
Это не кажется таким уж сложным, это довольно просто, но так ли это на самом деле?
В реальной работе или приложениях нам также может потребоваться указать путь к хранилищу файлов, использовать случайное число в качестве имени файла журнала, отобразить строки кода вывода конкретной информации, дату вывода информации журнала и метод записи журнала и т. д. Подумайте еще раз:
Конкретный код выглядит следующим образом:import os
import logging
import uuid
from logging import Handler, FileHandler, StreamHandler
class PathFileHandler(FileHandler):
def __init__(self, path, filename, mode='a', encoding=None, delay=False):
filename = os.fspath(filename)
if not os.path.exists(path):
os.mkdir(path)
self.baseFilename = os.path.join(path, filename)
self.mode = mode
self.encoding = encoding
self.delay = delay
if delay:
Handler.__init__(self)
self.stream = None
else:
StreamHandler.__init__(self, self._open())
class Loggers(object):
# 日志级别关系映射
level_relations = {
'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING,
'error': logging.ERROR, 'critical': logging.CRITICAL
}
def __init__(self, filename='{uid}.log'.format(uid=uuid.uuid4()), level='info', log_dir='log',
fmt='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
self.logger = logging.getLogger(filename)
abspath = os.path.dirname(os.path.abspath(__file__))
self.directory = os.path.join(abspath, log_dir)
format_str = logging.Formatter(fmt) # 设置日志格式
self.logger.setLevel(self.level_relations.get(level)) # 设置日志级别
stream_handler = logging.StreamHandler() # 往屏幕上输出
stream_handler.setFormatter(format_str)
file_handler = PathFileHandler(path=self.directory, filename=filename, mode='a')
file_handler.setFormatter(format_str)
self.logger.addHandler(stream_handler)
self.logger.addHandler(file_handler)
if __name__ == "__main__":
txt = "关注公众号【进击的 Coder】,回复『日志代码』可以领取文章中完整的代码以及流程图"
log = Loggers(level='debug')
log.logger.info(4)
log.logger.info(5)
log.logger.info(txt)
После сохранения и запуска файла результат выполнения показан на следующем рисунке:
Лог действительно выводится в консоль, посмотрим, генерируются ли указанные файлы и папки в директории:
После открытия файла вы можете увидеть вывод внутри:
как правильно учиться
Вы шаг за шагом наблюдаете за введением статьи и ждете заключения блогера?
Это запустить с кодом и запустить его снова?
Нет, это нужно делать, читая статью, размышляя и исследуя пример кода, где можно улучшить, а где лучше спроектировать. Если вам нужен пример кода и блок-схема, используемые в статье, обратите внимание на общедоступную учетную запись WeChat [Coder of Attack] и ответьте на «Код журнала», чтобы получить полный код и блок-схему в статье. Ведь учеба — это тяжелая работа.
Использованная литература: