logging模块

本篇文章,主要讲解Python内置的logging模型的使用。logging模块用来记录日志

日志级别

logging默认设定了如下几个日志级别,其中数值越高表示级别越高。

级别 数值 信息示例
CRITICAL 50 严重错误,表明程序已不能继续执行
ERROR 40 严重问题,程序某些功能已经不能正常执行
WARNING* 30 表明有已经或即将发生的意外。程序仍按预期进行。为默认级别。
INFO 20 确认程序按预期允许
DEBUG 10 细节信息,仅当诊断问题时使用
NOTSET 0 所有信息

触发日志

针对不同的日志级别,有相对应的方法来触发不同级别的日志。

import logging

logging.debug("this is a debug message")
logging.info("this is a info message")
logging.warning("this is a warning message")
logging.error("this is an error message")
logging.critical("this is a critical message")

默认情况下,会将级别≥WARNING的日志信息输出到console中。

工作原理

logging内部按照这个流程图工作:

  • 接收到日志触发后,先判断日志级别是否和Logger的级别匹配

    • 不匹配就不记录

    • 匹配就创建一个LogRecord,并判断是否被Logger内的filter过滤

      • 过滤的话就不记录

      • 不过滤的话,就传给当前的Logger内的handler处理

        • 日志级别是否与handler的级别匹配

          • 不匹配就不记录
          • 匹配的话就判断是否被handler内的filter过滤
            • 过滤的话不记录
            • 没有过滤的话就根据formatter进行记录
        • 判断logger的propagate属性是否为True

          • False则结束
          • True,则判断当前logger是否有父logger
            • 没有则结束
            • 有的话,则转入父logger处理

Formatter(格式器)

格式器限制了日志信息最终记录的结构和内容。

有两种方法来创建自定义的格式器:

  • 实例化Formatter类
from logging import Formatter
myFormatter = Formatter(fmt=None, datefmt=None, style='%')
  • 创建Formatter子类,并重写format和formatException方法
class MyFormatter(Formatter):
    def formatException(self, exc_info):
        '''
        Format an exception so that it prints on a single line
        '''
        result = super().formatException(exc_info)
        return repr(result)
    
    def format(self, record):
        s = super().format(record)
        if record.exc_text:
            s = s.replace('\n', '') + '|'
        return s

参数说明

  • fmt:定义日志显示的内容和格式,例如 "%(asctime)s %(message)s"。fmt中主要由LogRecord属性组成,记录了要显示哪些信息和其显示的顺序
  • datefmt:定义日期的显示格式,例如"%Y-%m-%d %I:%M:%S %p",此处的格式与time.strftime()一致
  • style:是fmt字符串中使用哪种样式字符串替换。有三个可选"%","{" 和"$"。
    • % : 对应%(attrname)s样式
    • { :对应{attrname}样式
    • $ :对应${attrname}样式

LogRecord属性

Filter(过滤器)

过滤器用来在判断LogRecord是否要被过滤,可以通过创建Filter类的子类,并重写filter方法,来创建自定义的过滤器。

from logging import Filter

class MyFilter(Filter):
    def filter(self, record):
        # 
        return True

相关说明:

  • filter方法返回True则不过滤这条日志,返回False则过滤这条日志
  • fiter方法中也可以对日志进行修改和操作

Handler(处理器)

处理器负责将适当的日志信息分派给处理器的指定目标。例如将日志输出在客户端,文件或邮件输出等。

系统中现有处理器

  • StreamHandler: 实例发送消息到流,控制台中
  • FileHandler: 实例将消息发送到硬盘文件
  • BaseRotatingHandler:轮转日志文件的处理器基类,使用中使用RotatingFileHandler或TimedRotatingFileHandler类
    • RotatingFileHandler:实例将消息发送到硬盘文件,支持最大日志文件大小和日志文件轮换
    • TimedRotatingFileHandler:实例将消息发送到硬盘文件,以特定的时间间隔轮换日志文件
  • SMTPHandler:实例将消息发送到指定的电子邮件地址

管理过滤器

通过addFilter()removeFilter()方法来管理处理器中的过滤器

管理格式器

通过setFormater()方法来指定处理器使用的格式器

Logger(记录器)

记录器具有如下几个作用:

  • 配置其处理的日志级别
  • 配置Filter
  • 配置Handler
  • 触发日志,用于创建日志信息

创建Logger

# 创建logger
logger = logging.getLogger("name1")
logger.setLevel(logging.INFO)
  • getLogger用于创建一个logger实例对象,其中name1为名称,如果name1.name2这表示创建一个name1下面的子记录器name2
  • setLevel用于设定该logger实例对象所对应的日志等级

管理处理器

通过addHandler()removeHandler()方法来管理处理器

# 创建handler
ch = logging.StreamHandler()
# 设置处理器处理日志等级
ch.setLevel(logging.INFO)

## 创建格式器
formatter = logging.Formatter("{asctime} - {levelname} - {message}", type="{")

## 处理器设置格式器
ch.setFormatter(formatter)

## 记录器中添加处理器
logger.addHandler(ch)

管理过滤器

通过addFilter()removeFilter()方法来管理过滤器。

创建日志

通过debug()info()warning()error()critical()exception()方法来创建日志消息。

配置方式

代码方式

import logging

# 创建logger
logger = logging.getLogger('simple')
# 设置logger日志级别
logger.setLevel(logging.INFO)

# 创建处理器
ch = logging.StreamHandler()
# 设置处理器日志级别
ch.setLevel(logging.INFO)

# 创建格式器
formatter = logging.Formatter('{asctime} - {levelname} - {message}', type="{")

# 处理器中添加格式器
ch.addFormatter(formatter)

# 记录器中添加处理器
logger.addHandler(ch)

# 触发日志
logger.info('this is an info message')
logger.warning('this is a warning message')
logger.error('this is an error message')
logger.critical('this is a critical message')

配置文件

利用logging.config.fileConfig方法读取配置文件完成logger的配置

import logging
import logging.config

# 读取配置文件完成初始配置
logging.config.fileConfig('logging.conf')

# 创建记录器
logger = logging.getLogger('simple')

# 触发日志
logger.info('this is an info message')
logger.warning('this is a warning message')
logger.error('this is an error message')
logger.critical('this is a critical message')

配置文件内容

# logging.conf配置文件

# 配置记录器
[loggers]
keys=root,simple

# 配置处理器
[handlers]
keys=consoleHandler

# 配置格式器
[formatters]
keys=simpleFormatter

# 配置父类记录器
[logger_root]
level=DEBUG
handlers=consoleHandler

# 配置子记录器
[logger_simple]
level=DEBUG
handlers=consoleHandler
qualname=simple
propagate=0

# 配置处理器
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

# 配置格式器
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

配置字典

利用logging.config.dictConfig方法读取配置字典完成logger的配置

字典内容

# 配置字典
version: 1
formatters:
  simple:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: simple
    stream: ext://sys.stdout
loggers:
  simpleExample:
    level: DEBUG
    handlers: [console]
    propagate: no
root:
  level: DEBUG
  handlers: [console]
posted @ 2024-06-21 16:51  Python习者  阅读(25)  评论(0)    收藏  举报