logging库的使用

级别 何时使用
DEBUG 详细信息,典型地调试问题时会感兴趣。 详细的debug信息。
INFO 证明事情按预期工作。 关键事件。
WARNING 表明发生了一些意外,或者不久的将来会发生问题(如‘磁盘满了’)。软件还是在正常工作。
ERROR 由于更严重的问题,软件已不能执行一些功能了。 一般错误消息。
CRITICAL 严重错误,表明软件已不能继续运行了。
NOTICE 不是错误,但是可能需要处理。普通但是重要的事件。
ALERT 需要立即修复,例如系统数据库损坏。
EMERGENCY 紧急情况,系统不可用(例如系统崩溃),一般会通知所有用户。

一、基本的使用方式

logging.basicConfig(
    filename="test.log" # 设置日志的文件名
    filemode="w" # 设置日志的写入方式
    format="%(asctime)s|%(levelname)s|%(filename)s:%(lineno)s|%(message)s", # 设置输出格式
    datefmt = "%Y-%m-%d %H:%M:%S",# 设置输出日期的格式
    level=logging.DEBUG # 设置log等级
)

logging.debug("hahah") # 输出日志

并不推荐使用这种方式,这种方式操作的是整个logging库的底层默认值,既root用户的设置(这么说可能不是很准确,但我也没太弄明白),后续使用中可能会遇到继承相关的问题。


二、logging库中的组件

名称 作用
Loggers 记录器,提供应用程序代码直接使用的接口
Handlers 处理器,将记录器产生的日志发送至目的地
Filters 过滤器,提供更好的粒度控制,决定哪些日志会被输出
Formatters 格式化器,设置日志内容的组成结构和消息字段

2.1 loggers记录器

loggers(记录器)可以看成一种载体

image-20220801124830651
<注:过滤器是否可以在loggers或handlers中同时存在多个,我暂时还没弄清楚,但1个是肯定可以的
import logging # 后续将不再重复声明

guo_logger = logging.getlogger("guo") # 创建一个记录器 
guo_logger.addHandler(<处理器的变量名>) # 为记录器设置一个处理器
guo_logger.addFilter(<过滤器变量名>) # 为记录器设置一个过滤器
为什么用guo?因为我姓国  ̄▽ ̄

”guo”为此过滤器提供了唯一的标识,同时也定义了继承关系

例如:

guo_logger = logging.getLogger("guo")
guo_logger.setLevel(logging.DEBUG)
guo1_logger = logging.getLogger("guo.a")

那么,guo1_logger,将会继承guo_logger的全部设置,不仅包括日志等级

“."的作用就像电脑里文件路径"/"的作用一样,”guo”会包括“guo.a",也会包括“guo.a.b"

对于不希望guo1_logger继承的处理器(handlers),我们可以使用过滤器(filter)对处理器进行设置,详见后文


在logging.getlogger()生成的记录器中:

​ 默认的日志等级为“warning”,记录器是各个处理器(handler)的载体,如果记录器中的处理器(handler)的日志等级低于记录器的日志等级,处理器(handler)将不会进行相应的写日志操作,可以理解为,记录器规定了记录时的最低等级,处理器规定了处理时的最低等级

image-20220801232406693

​ 默认的处理器(handler)是StreamHandler,只会向终端打印日志信息


2.2 Handlers 处理器

guo_consoleHandler = logging.StreamHandler() # 生成一个向stream(数据流)输出的处理器
# StreamHandler(stream),参数stream默认值为sys.stderr(通过查看源码可知)
guo_consoleHandler.setFormatter(<格式化器的变量名>) # 为处理器设置格式化器->设置处理器输出日志时的格式
guo_consoleHandler.addFilter(<过滤器变量名>) # 为处理器设置过滤器
2.2.1 Handlers 处理器种类
处理器名称 解释 使用提示
Streamhandler 将日志输出在终端(控制台)上的处理器 logging.StreamHandler()
Filehandler 将日志保存到磁盘文件的处理器 logging.FileHandler(filename="")
BaseRotatingHandler 基本的日志轮转方式 logging.handlers.BaseRotatingHandler()
具体的参数没有找到
RotatingHandler 支持日志文件按大小轮转 logging.handlers.RotatingHandler
是后面类的基础
RotatingHandler 按照日志文件大小轮转,继承自RotatingHandler logging.handlers.RotatingHandler
TimeRotatingHandler 按照时间轮转,继承自RotatingHandler logging.handlers.TimeRotatingHandler
SMTPHandler 远程输出日志到邮件地址 logging.handlers.SMTPHandler()
HTTPHandler 通过GET或POST远程输出到HTTP服务器 logging.handlers.HTTPHandler()

具体各个handlers控制器的使用细节,用的时候再查吧。。。

2.3 Formatters 格式化器

guo_formatter = logging.Formatter("%(asctime)s|%(levelname)8s|%(filename)10s|%(lineno)s|%(message)s") # 定义一个格式化器
guo_formatter.datafmt = '%Y-%m-%d %H:%M' # 定义#(asctime)s中,日期的显示格式

实际上,logging.Formatter()中的第二个参数就是datafmt,因此以上代码可简写为:

guo_formatter = logging.Formatter("%(asctime)s|%(levelname)8s|%(filename)10s|%(lineno)s|%(message)s",'%Y-%m-%d %H:%M')
2.3.1 Formatters中的格式
属性 格式 描述
asctime %(asctime)s 日志产生的时间,默认格式为msecs2003-07-0816:49:45,896
msecs %(msecs)d 日志生成时间的亳秒部分
created %(created)f time.tme)生成的日志创建时间戳
message %(message)s 具体的日志信息
filename %(filename)s 生成日志的程序名
name %(name)s 日志调用者
funcname %( funcname)s 调用日志的函数名
levelname %(levelname)s 日志级別( DEBUG,INFO, WARNING, 'ERRORCRITICAL)
levene %( leveling)s 日志级别对应的数值
lineno %(lineno)d 日志所针对的代码行号(如果可用的话)
module %( module)s 生成日志的模块名
pathname %( pathname)s 生成日志的文件的完整路径
process %( (process)d 生成日志的进程D(如果可用)
processname (processname)s 进程名(如果可用)
thread %(thread)d 生成日志的线程D(如果可用)
threadname %( threadname)s 线程名(如果可用)

2.4 Filter过滤器

guo_fit = logging.Filter("guo") # 定义一个过滤器

如果把过滤器(fliter)配置到记录器(loggers)中,那么只有名称中包括“guo”字段的记录器(loggers)才能进行记录操作

如果把过滤器(fliter)配置到处理器(handlers)中,那么只有名称中包括“guo”字段的处理器(handlers)才能进行处理操作

image-20220801124830651

过滤器的参数“guo”是可以自定义的,它也遵守记录器(loggers)的命名规则

假设,有一个名字为”guo“的记录器、一个名字为“guo.a"的记录器和一个名字为”guo.b"的记录器。

“guo.a”和“guo.b"两个记录器中的处理器会继承记录器”guo“的

image-20220803130628760

例子如下:

import logging
#创建记录器
logger_guo = logging.getLogger("guo")
logger_guo_a = logging.getLogger("guo.a")
logger_guo_b = logging.getLogger("guo.b")
#创建格式化器
formatter_0 = logging.Formatter("%(asctime)r|%(levelname)8r|%(name)r|%(message)r")
#创建处理器并为处理器设置格式化器
console_hander = logging.StreamHandler()
console_hander.setFormatter(formatter_0)
#为记录器设置处理器
logger_guo.addHandler(console_hander)

#创建并为处理器设置过滤器
# fit = logging.Filter("guo.a") #创建过滤器
# console_hander.addFilter(fit) #为处理器添加过滤器

# 测试各个记录器
logger_guo.warning("test")# 此处用warning是因为记录器默认的日志等级为warning

logger_guo_a.warning("test1")

logger_guo_b.warning("test2")

在未设置过滤器时,输出结果为:

'2022-08-03 13:31:28,758'|'WARNING'|'guo'|'test'
'2022-08-03 13:31:28,759'|'WARNING'|'guo.a'|'test1'
'2022-08-03 13:31:28,759'|'WARNING'|'guo.b'|'test2'

在设置过滤器后,输出结果为:

'2022-08-03 13:44:11,869'|'WARNING'|'guo.a'|'test1'

此时,虽然处理器是设置在“guo”中的,但是“guo”本身已经无法使用此处理器了,只有名称为“guo.a"的记录器才可以使用此处理器,不止”guo.a"可以使用,“guo.a.a"也可以使用

例子如下:

import logging
#创建记录器
logger_guo = logging.getLogger("guo")
logger_guo_a = logging.getLogger("guo.a")
logger_guo_a_a = logging.getLogger("guo.a.a")
logger_guo_b = logging.getLogger("guo.b")
#创建格式化器
formatter_0 = logging.Formatter("%(asctime)r|%(levelname)8r|%(name)r|%(message)r")
#创建处理器并为处理器设置格式化器
console_hander = logging.StreamHandler()
console_hander.setFormatter(formatter_0)
#为记录器设置处理器
logger_guo.addHandler(console_hander)

#创建并为处理器设置过滤器
# fit = logging.Filter("guo.a") #创建过滤器
# console_hander.addFilter(fit) #为处理器添加过滤器


# 测试各个记录器
logger_guo.warning("test")# 此处用warning是因为记录器默认的日志等级为warning

logger_guo_a.warning("test1")
logger_guo_a_a.warning("test1_0")

logger_guo_b.warning("test2")

输出结果为:

'2022-08-03 13:54:01,778'|'WARNING'|'guo.a'|'test1'
'2022-08-03 13:54:01,778'|'WARNING'|'guo.a.a'|'test1_0'

三、一些零碎的想法

​ 没有太理解过滤器存在的意义,如果我希望一个处理器(handlers)只在记录器”guo.a"中生效,那我为什么不直接把处理器放到记录器”guo.a"中呢?如果是希望处理器可以复用(定义一个处理器,用在多个记录器上),那么我为处理器定义了过滤器,那这个处理器就和记录器彻底绑定了,而且过滤器只能过滤一种“guo.a",如果我想让”guo.b"也可以使用,但不想让”guo.c"使用,这种情况我就只能把处理器从“guo”中拿出来,分别放到“guo.a"和”guo.b"中,那我过滤器存在的意义是什么呢。。。

​ 也许是我对过滤器的用法还不了解?但我一直没找到可以参考的例子,,,


参考教程:https://www.bilibili.com/video/BV1sK4y1x7e1
教程后半部分,利用配置文件进行设置的方法我并没有整理,因为我还没弄明白前半部分

posted @ 2022-08-03 15:15  Cat-shark  阅读(307)  评论(0)    收藏  举报