Logging库日志级别
级别 | 级别数值 | 使用时机 |
---|---|---|
DEBUG | 10 | 详细信息,常用于调试 |
INFO | 20 | 程序正常运行过程中产生的一些信息 |
WARNNING | 30 | 警告用户,虽然程序还在正常工作,但有可能发生错误 |
ERROR | 40 | 由于更严重的问题,程序已不能执行一些功能了 |
CRITICAL | 50 | 严重错误,程序已不能继续运行 |
默认的日志级别是warning
我们来看一下代码
1 | import logging |
结果
1 | WARNING:root:This is an warning |
正常不会打印出debug和info日志。现在我们更改下日志输出的级别,将日志的输出级别改成DEBUG
1 | import logging |
结果
1 | DEBUG:root:This is a debug message |
现在打印出了所有的日志了
Logging.basicConfig()
logging.basicConfig() 的参数除了日志等级的这个参数可以设置以外,还可以设置其他的参数,比如:
格式 | 描述 |
---|---|
filename | 使用指定的文件名创建一个 FileHandler ,而不是 StreamHandler 。 |
filemode | 如果指定了 filename,则用此 模式 打开该文件。 默认模式为 'a' 。 |
format | 使用指定的格式字符串作为处理器。 默认为属性以冒号分隔的 levelname , name 和 message 。 |
datefmt | 使用指定的日期/时间格式,与 time.strftime() 所接受的格式相同。 |
style | 如果指定了 format,将为格式字符串使用此风格。 '%' , '{' 或 '$' 分别对应于 printf 风格, str.format() 或 string.Template 。 默认为 '%' 。 |
level | 设置根记录器级别为指定的 level. |
stream | 使用指定的流初始化 StreamHandler 。 请注意此参数与 filename 不兼容 —— 如果两者同时存在,则会引发 ValueError 。 |
handlers | 如果指定,这应为一个包含要加入根日志记录器的已创建处理器的可迭代对象。 任何尚未设置格式描述符的处理器将被设置为在此函数中创建的默认格式描述符。 请注意此参数与 filename 或 stream 不兼容 —— 如果两者同时存在,则会引发 ValueError 。 |
force | 如果将此关键字参数指定为 true,则在执行其他参数指定的配置之前,将移除并关闭附加到根记录器的所有现有处理器。 |
encoding | 如果此关键字参数与 filename 一同被指定,则其值会在创建 FileHandler 时被使用,因而也会在打开输出文件时被使用。 |
errors | 如果此关键字参数与 filename 一同被指定,则其值会在创建 FileHandler 时被使用,因而也会在打开输出文件时被使用。 如果未指定,则会使用值 ‘backslashreplace’。 请注意如果指定为 None ,它将被原样传给 open() ,这意味着它将会当作传入 ‘errors’ 一样处理。 |
上表提到的日志的输出格式参数format,其控制着日志输出的一些格式:
属性名称 | 格式 | 描述 |
---|---|---|
args | 此属性不需要用户进行格式化。 | 合并到 msg 以产生 message 的包含参数的元组,或是其中的值将被用于合并的字典(当只有一个参数且其类型为字典时)。 |
asctime | %(asctime)s |
表示人类易读的 LogRecord 生成时间。 默认形式为 ‘2003-07-08 16:49:45,896’ (逗号之后的数字为时间的毫秒部分)。 |
created | %(created)f |
LogRecord 被创建的时间(即 time.time() 的返回值)。 |
exc_info | 此属性不需要用户进行格式化。 | 异常元组(例如 sys.exc_info )或者如未发生异常则为 None 。 |
filename | %(filename)s |
pathname 的文件名部分。 |
funcName | %(funcName)s |
函数名包括调用日志记录. |
levelname | %(levelname)s |
消息文本记录级别('DEBUG' ,'INFO' ,'WARNING' ,'ERROR' ,'CRITICAL' )。 |
levelno | %(levelno)s |
消息数字的记录级别 (DEBUG , INFO , WARNING , ERROR , CRITICAL ). |
lineno | %(lineno)d |
发出日志记录调用所在的源行号(如果可用)。 |
message | %(message)s |
记入日志的消息,即 msg % args 的结果。 这是在发起调用 Formatter.format() 时设置的。 |
module | %(module)s |
模块 (filename 的名称部分)。 |
msecs | %(msecs)d |
LogRecord 被创建的时间的毫秒部分。 |
msg | 此属性不需要用户进行格式化。 | 在原始日志记录调用中传入的格式字符串。 与 args 合并以产生 message ,或是一个任意对象 (参见 使用任意对象作为消息)。 |
name | %(name)s |
用于记录调用的日志记录器名称。 |
pathname | %(pathname)s |
发出日志记录调用的源文件的完整路径名(如果可用)。 |
process | %(process)d |
进程ID(如果可用) |
processName | %(processName)s |
进程名(如果可用) |
relativeCreated | %(relativeCreated)d |
以毫秒数表示的 LogRecord 被创建的时间,即相对于 logging 模块被加载时间的差值。 |
stack_info | 此属性不需要用户进行格式化。 | 当前线程中从堆栈底部起向上直到包括日志记录调用并引发创建当前记录堆栈帧创建的堆栈帧信息(如果可用)。 |
thread | %(thread)d |
线程ID(如果可用) |
threadName | %(threadName)s |
线程名(如果可用) |
我们来看看怎么使用:
1 | import logging |
filemode也是一个常用的参数,不设的话默认为'a'
,即追加模式;也可以设为'w'
,那么每次写日志会覆盖之前的日志。
上述产生的日志文件message.log
结果如下:
1 | 2024-04-10 22:35:26,490 - root - test.py:8 - DEBUG - This is a debug message |
Logging组件
Logging中除了以上的一些设置之外,logging还提供了几个组件(类)供我们实现一些特殊的功能,它们主要是:
组件名称 | 对应类名 | 对应描述 |
---|---|---|
日志器 | Logger | 提供了应用程序可以一直使用的接口 |
处理器 | Handler | 将创建的日志记录发送到合适的目的地输出 |
过滤器 | Filter | 提供了更细颗粒度的控制工具来决定输出哪条日志记录,丢弃哪条日志记录 |
格式器 | Formatter | 决定日志记录的最终输出格式 |
这些组件共同完成日志的配置和输出:
Logger
需要通过handler
将日志信息输出到目标位置,目标位置可以是sys.stdout
和文件等。- 不同的Handler可以将日志输出到不同的位置(不同的日志文件)。
Logger
可以设置多个handler
将同一条日志记录输出到不同的位置。- 每个
Handler
都可以设置自己的filter
从而实现日志过滤,保留实际项目中需要的日志。 formatter
实现同一条日志以不同的格式输出到不同的地方。
简单的说就是:日志器作为入口,通过设置处理器的方式将日志输出,处理器再通过过滤器和格式器对日志进行相应的处理操作。
我们来简单的介绍一下这些组件中一些常用的方法:
Logger 日志器
提供应用程序的调用接口
logger = logging.getLogger(__name__)
logger
是单例的决定日志记录的级别
logger.setLevel()
将日志内容传递到相关联的
headlers
中logger.addHandler() 和 logger.removeHandler()
方法 | 方法描述 |
---|---|
Logger.setLevel() | 设置日志器将会处理的日志消息级别 |
Logger.addHander() | 添加一个handler 对象 |
Logger.addFilter() | 添加一个filter 对象 |
Logger.removeHander() | 移除一个handler 对象 |
Logger.removeFilter() | 移除一个filter 对象 |
Logger.debug() | 设置DEBUG级别的日志记录 |
Logger.info() | 设置INFO级别的日志记录 |
Logger.exception() | 输出堆栈追踪信息 |
Logger.log() | 设置一个自定义的lever 参数来创建一个日志记录 |
Handler 处理器
Handler
将日志分发到不同的目的地。可以是文件、标准输出、邮件、或者通过socke
、http
等协议发送到任何地方
StreamHeadler
标准输出stdout
(如显示器)分发器
创建方法:sh = logging.StreamHandler(stream=None)
FileHandler
将日志保存到磁盘文件的处理器
创建方法:fh = logging.FileHandler(filename, mode='a', encoding=None, delay=False)
setFormatter():
设置当前handler对象使用的消息格式
方法 | 方法描述 |
---|---|
logging.StreamHandler() | 它可将日志记录输出发送到数据流例如 sys.stdout, sys.stderr 或任何文件型对象(或者更精确地说,任何支持 write() 和 flush() 方法的对象)。 |
logging.FileHandler() | 它可将日志记录输出到磁盘文件中 |
RotatingFileHandler() | 将日志消息发送到磁盘文件,支持日志文件按大小切割 |
BaseRotatingHandler() | 它是轮换文件处理程序类 |
TimedRotatingFileHandler() | 将日志消息发送到磁盘文件,并支持日志文件按时间切割 |
Fliter 过滤器
看名字大家就知道这是一个过滤类,那么过滤什么呢?
Filter可以被Handler和Logger用来做比之前设置的日志等级level更为细粒度的、更复杂的相关过滤功能。
简单的说Filter是一个过滤器基类,它只允许某个logger层级下的日志事件通过过滤,保存下来。该类定义如下:
1 | class logging.Filter(name='') |
过滤举例:
例如用 ‘A.B’ 初始化的 Filter,那么其允许Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’ 等日志记录的事件,logger‘A.BB’, ‘B.A.B’ 等就不满足过滤的条件。
如果用空字符串来对Filter初始化,所有日志记录的事件都将不会被过滤。
Formatter 格式器
Formater
主要负责日志的格式化输出的
构造方法:ft = logging.Formatter.__init__(fmt=None, datefmt=None, style=' %')
datefmt
默认是%Y-%m-%d %H:%M:%S
样式的
style
参数默认为百分符%,这表示%(<dictionary key>)s
格式的字符串
如果使用logging
的组件呢,来看下面的例子
1 | import logging |
结果如下
1 | 2024-04-10 23:46:28,312 [DEBUG] [test1.py:26] [applog] This is a debug message |
配置文件
conf
形式配置文件
我们知道在**logging.basicConfig()**中,是进行一些日志的配置的,如果每次都去改动代码,那将变得十分的麻烦,特别是在程序发布或者上线的时候。所以我们可以使用一个什么好的方法来规避这个问题呢?有的,那就是配置文件。
我们在文件logging.conf中写入相关的信息,内容如下:
1 | [loggers] |
使用配置文件的代码如下:
1 | import logging.config |
结果
1 | 2024-04-11 00:28:56,077 [DEBUG] [test2.py:9] [appname] debug message |
自定义logger
日志输出文件
以上介绍的知识点,大家在平时或在实际的项目中使用基本上就足够了,下面我们简单的介绍一下怎么进行自定义logger进行日志的输出。
我们写一个sel_def_logger.py文件,文件中的定义一个类,内容如下:
1 | import os |
那么使用这个类的方法可以这样写:
1 | import datetime |