python logging模块详解

本文详细介绍了Python内置的logging模块,包括日志器(Logger)、处理器(Handler)、筛选器(Filter)和格式器(Formatter)的使用方法。讲解了如何设置日志级别、处理器类型如StreamHandler、FileHandler等,以及如何配置日志记录,帮助读者全面理解并应用logging模块。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

logging库采用模块化方法,并提供了几类组件:记录器,处理程序,过滤器和格式化程序。

  • 记录器(Logger):提供应用程序代码直接使用的接口。

  • 处理器(Handler):将日志记录(由记录器创建)发送到适当的目的地。

  • 筛选器(Filter):提供了更细粒度的功能,用于确定要输出的日志记录。

  • 格式器(Formatter):程序在最终输出日志记录的内容格式。

logging的工作流程:以记录器Logger为对象,设置合适的处理器Handler,辅助以筛选器Filter、格式器Formatter,设置日志级别以及常用的方法,最终输出理想的日志记录给到指定目标

  • 一个Logger可以包含多个Handler;
  • 每个Handler可以设置自己的Filter和Formatter;
    在这里插入图片描述

一、基本使用

import logging

# 创建日志器对象
logger = logging.getLogger(__name__)

# 设置logger可输出日志级别范围
logger.setLevel(logging.DEBUG)

# 添加控制台handler,用于输出日志到控制台
console_handler = logging.StreamHandler()
# 添加日志文件handler,用于输出日志到文件中
file_handler = logging.FileHandler(filename='log.log', encoding='UTF-8')

# 将handler添加到日志器中
logger.addHandler(console_handler)
logger.addHandler(file_handler)

# 设置格式并赋予handler
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)

# 输出不同级别日志
logger.debug("============【开始测试】====================")
logger.info("============【开始测试】====================")
logger.warning("============【开始测试】====================")
logger.critical("============【开始测试】====================")
logger.error("============【开始测试】====================")

输出结果:
在这里插入图片描述
上面是一个完整的实例,接下来详细讲logging模块

二、日志器Logger

logging模块中,要输出日志,日志器是必不可少的
创建日志器:

logger = logging.getLogger()

日志器名称:
1、若没有指定日志器名称,则默认为root

print(logging.getLogger())

输出结果:<RootLogger root (WARNING)>

2、当有多个具有相同名称的日志器,调用任一日志器时将返回对同一记录器对象的引用
注意:这种情况下日志器间的处理器handler是相互叠加,由于logging每次输出日志记录数量=handler数量,我们会看到logger.warning("输出一条日志记录")的实际结果会打印多条日志记录

import logging

logger = logging.getLogger()  # 日志器名称默认为root
logger1 = logging.getLogger()  # 日志器名称默认为root

# 设置两个处理器handler
console_handler = logging.StreamHandler()
console_handler1 = logging.StreamHandler()

# 给两个相同名称的logger添加上处理器
logger.addHandler(console_handler)
logger1.addHandler(console_handler1)

# 设置一下格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
console_handler1.setFormatter(formatter)

# 输出日志记录
logger1.warning("输出一条日志记录")

输出结果:
在这里插入图片描述
从这里看出来,logger1在代码中,我们只给他添加了一个handler,但是由于和logger名称相同,调用任一一个logger,他们的处理器相加为2了,且因日志记录数量=处理器数量,所以这里代码只记录一条,但实际结果是两条日志记录,因此不太建议这么用

3、通常建议使用__name__来命名日志器,或者自定义的名称,这样日志器名称不相同,则不会产生handler叠加的现象

import logging

logger = logging.getLogger(__name__)  # 日志器名称为包名
logger1 = logging.getLogger("DIY")  # 日志器名称为DIY

# 设置两个处理器handler
console_handler = logging.StreamHandler()
console_handler1 = logging.StreamHandler()

# 给两个不同名称的logger添加上处理器
logger.addHandler(console_handler)
logger1.addHandler(console_handler1)

# 设置一下格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
console_handler1.setFormatter(formatter)

# 输出日志记录
logger1.warning("输出一条日志记录")

输出结果:
在这里插入图片描述
这里两个logger名称不相同,因此没有handler相加的现象,所以这里正常输出一条日志记录

日志器数量
从上面的例子也可以看出,logger日志器的数量可以是多数的,理论上应该是无限的

logger1 = logging.getLogger(__name__)
logger2 = logging.getLogger(__name__)
logger3 = logging.getLogger(__name__)
logger4 = logging.getLogger(__name__)
logger5 = logging.getLogger(__name__)

三、处理器Handler

处理器负责将日志消息发送到不同目标,例如:控制台,日志文件,电子邮件,等目标
logging模块提供很多个类型的处理器
在这里插入图片描述

StreamHandler

日志记录发送到控制台中

logging.StreamHandler(stream=None

参数:
stream:默认为None,日志输出到sys.stderr;指定stream的话中,则日志输出到指定stream

FileHandler

日志记录发送到磁盘文件中

logging.FileHandler(filename, mode='a', encoding=None, delay=False)

参数:
filename:只填写文件名称,则默认新增文件到当前工作目录;填写工作路径+文件名称,则新增到对应工作目录
mode:默认a模式,可自定义
encoding:默认为None,可自定义
delay:默认为False,为True时,将文件打开延迟到第一次调用时进行emit()

NullHandler

不做任何事情的处理器,防止sys.stderr在没有日志记录配置的情况下将库的已记录事件输出

logging.NullHandler()

WatchedFileHandler

该处理器旨在在Unix / Linux下使用,它监视文件以查看自上一次发出以来是否已更改。(如果文件的设备或索引节点已更改,则认为该文件已更改。)如果文件已更改,则关闭旧文件流,并打开该文件以获取新的流,不适合在Windows下使用

logging.handlers.WatchedFileHandler(filename, mode='a', encoding=None, delay=False)

RotatingFileHandler

日志记录到文件中,且支持指定日志文件大小,备份文件数量

logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False)

参数:
maxBytes:日志文件大小,单位为字节
backupCount:备份文件数量

注意:当maxBytes或backupCount中的任何一个为零,则永远不会发生过渡

例子:使用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分别等。

实例:

import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger('logger')
logger.setLevel(logging.DEBUG)
rotating_handler = logging.handlers.RotatingFileHandler('rotating_log.log', encoding='UTF-8', maxBytes=1024, backupCount=2)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
rotating_handler.setFormatter(formatter)
logger.addHandler(rotating_handler)

# 输出日志记录
logger.debug("============【开始测试】====================")
logger.info("============【开始测试】====================")
logger.warning("============【开始测试】====================")
logger.error("============【开始测试】====================")
logger.critical("============【开始测试】====================")

输出结果:
在这里插入图片描述

TimedRotatingFileHandler

日志记录到文件中,支持按时间间隔来更新日志

logging.handlers.TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None)

参数:
when:不同值对应不同时间类型,以字符串填入,不区分大小写
在这里插入图片描述
基于工作日的轮换时,将“ W0”指定为星期一,将“ W1”指定为星期二,依此类推,直到“ W6”指定为星期日。在这种情况下,不使用为interval传递的值

关于过渡时间:首次(在创建处理程序时)计算下一个过渡时间时,将使用现有日志文件的最后修改时间或当前时间来计算下一个轮换发生的时间。

interval:时间长度,与when结合使用

backupCount:如果backupCount不为零,则最多将保留backupCount数的文件,并且如果发生翻转时将创建更多文件,则最早的文件将被删除。删除逻辑使用间隔来确定要删除的文件,因此更改间隔可能会留下旧文件。

utc:默认为False,使用本地时间;为True时,使用UTC时间

actime:默认为None,若非None时,必须是一个datetime.time实例,该实例指定发生翻转的一天中的时间,对于将翻转设置为“在午夜”或“在特定工作日”发生的情况。请注意,在这些情况下,atTime值可有效地用于计算初始 翻转,随后的翻转将通过正常间隔计算来计算。
在这里插入图片描述
实例:

import logging
from logging.handlers import RotatingFileHandler
from datetime import time

logger = logging.getLogger('logger')
logger.setLevel(logging.DEBUG)
time_rotating_handler1 = logging.handlers.TimedRotatingFileHandler('time_rotating_log.log', when='M', interval=1.5, backupCount=2, encoding='UTF-8', delay=False, utc=False, atTime=time)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
time_rotating_handler1.setFormatter(formatter)
logger.addHandler(time_rotating_handler1)

# 输出日志记录
logger.debug("============【开始测试】====================")
logger.info("============【开始测试】====================")
logger.warning("===========&
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值