logging模块的使用 2021-03-10

日志的级别:

  • DEBUG
  • INFO
  • WARNNING
  • ERROR
  • CRITICAL
作者代码可以见 代码

几个重要的概念

    1. Logger:记录器,是应用程序直接使用的借口
    1. Handler处理器,将(记录器)产生的日志记录发送往合适的借口
    1. Filter:过滤器,提供更好的输出控制,可以决定输出哪些日志记录
Logger

 Logger是一个树级的结构,使用debug,info等前一定要创建Logger实例,即创建一个记录器。如果没有显式的创建,默认创建一个root logger,并应用默认的日志级别(WARN),处理器Handler(StreamHandler,即讲日志信息打印输出在标准的输出上),和格式化器(默认的格式是第一个简单使用程序中输出的样式)。

#创建方法:
logger = logging.getLogger(logger_name)

 创建Logger实例后,可以使用如下的方法设置日志级别,增加处理器Handler。

  • logger.setLevel(logging.DEBUG)
  • logger.addHadnler(handler_name)
  • logger.removeHandler(handler_name)
Handler处理器

 Handler的处理器类型有很多种,常见有三个,Streamhandler,FileHandler,NullHandler
 创建StreamHandler后可以使用如下的方法设置日志级别(level),格式化器(Formatter),过滤器(Filter):

  • ch.setLevel(logging.WARN)
  • ch.setFormatter(formatter_name)
  • ch.addFilter(filter_name)
  • ch.removeFilter(filter_name)
#StreamHandler的创建方法:
sh = logging.StreamHandler(stream=None)
#FileHandler创建方法
fh = logging.FileHandler(filename,mode='a',encoding=None,delay=False)
#NullHandler创建方法
这玩意没什么用,由库开发者使用
Formatter格式化器

 使用Formatter对象设置日志信息的最后贵的,结构和内容,默认的时间格式位%Y-%m-%d%H:%M:%S

#创建方法:
formatter = logging.Formatter(fmt=None,datafmt=None)
其中fmt是消息的格式化串,datafmt是日志字符串,如果不指定fmt将会使用%(message)s' 如果不指明datefmt将使ISO8601的日期格式。
Filter过滤器

 Handler和Logger都可以使用Filter完成比级别完成更复杂的过滤,Filter基类仅允许指定Logger层次一下的事件,例如使用'A.B'初始化的Filter允许Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’等记录的事件,logger‘A.BB’, ‘B.A.B’ 等就不行。 如果用空字符串来初始化,所有的事件都接受。

filter = logger.Filter(name=' ')

Logger Handler Filte Formatter几种关系,该关系可以使用如下图进行描述:

几种实例之间的关系

由上图可以知,Logger是一个树形的结构,Logger可以包括多个Handler和Filter,一个Handler可以有多个Formatter和Filter,并且日志级别将会继承。

Logging的工作流程

Logging的工作流程
    1. 由上图可以知道,如果使用者的代码中产生了日志提交,首先进行判断登记等级是否大于Logger实例的等价,如果小于,会抛弃这个日志,否则进入下一步.
    1. 创建日志,使用注册到Logger中的Filter进行过滤,轮流进行过滤,如果有一个把他过滤掉了,终止。否则等所有的过滤完成后进入下一步。
    1. 日子继续往下流
    • 日志流向所有注册在Logger中的Handlers,首先判断等级够不够,接着判断有没有过滤器,都不能拒绝日志的话,将会格式化输出(会产生额外的信息,比如在哪个文件那一行等)。
    1. 判断日志能够进行传播,如果可以并且有父类Logger,那么将会送入父类进行处理。

几种配置方式

#下面是一些模块级别的函数:
getLogger返回指定name的日志记录器,name=None时候返回层级结构总为根级别的记录器,如果指定了name,name一般是用a. a.b a.b.c.d,这些名称自定义
logging.getLogger(name=None)

logging.GetLoggerClass() 返回标准的Logger类
常见的logging.debug('')都是在根记录器中产生消息

logging.disable(level=logging.CRITICAL),以为重载的形式会作用在所有的Logger,一般用来限制全局
logging.addLevelName(level,levelName) 自己定义一个等级对应的名字,如30对应一个MyDebug
logging.basicConfig(**   kwags) 使用磨人的Formatte创建一个StreamHandler并加入根日志记录起,如果没有为跟记录器定已处理程序,那么debug()等会自动调用basicConfig。如果根日志记录器配置了处理程序,不执行任何操作。
#logging.shutdown

 上述提到的支持一下参数:

名字 功能
filename 指定日志输出目标文件的文件名,指定该设置项后日志信心就不会被输出到控制台了
filemode 指定日志文件的打开模式,默认为'a'。需要注意的是,该选项要在filename指定时才有效
format 指定日志格式字符串,即指定日志输出时所包含的字段信息以及它们的顺序。logging模块定义的格式字段下面会列出。
datafmt 指定日期/时间格式。需要注意的是,该选项要在format中包含时间字段%(asctime)s时才有效
level 指定日志器的日志级别
stream 可以指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream。需要说明的是,stream和filename不能同时提供,否则会引发 ValueError异常
handlers 该选项如果被指定,它应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger。需要说明的是:filename、stream和handlers这三个配置项只能有一个存在,不能同时出现2个或3个,否则会引发ValueError异常。
encoding
errors
format参数中可能用到的格式化串:
  • %(name)s Logger的名字
  • %(levelno)s 数字形式的日志级别
  • %(levelname)s 文本形式的日志级别
  • %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
  • %(filename)s 调用日志输出函数的模块的文件名
  • %(module)s 调用日志输出函数的模块名
  • %(funcName)s 调用日志输出函数的函数名
  • %(lineno)d 调用日志输出函数的语句所在的代码行
  • %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
  • %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
  • %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
  • %(thread)d 线程ID。可能没有
  • %(threadName)s 线程名。可能没有
  • %(process)d 进程ID。可能没有
  • %(message)s用户输出的消息

一个例子

# -*- encoding:utf-8 -*-
import logging

# create logger
logger_name = "example"
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)

# create file handler
log_path = "./log.log"
fh = logging.FileHandler(log_path)
fh.setLevel(logging.WARN)

# create formatter
fmt = "%(asctime)-15s %(levelname)s %(filename)s %(lineno)d %(process)d %(message)s"
datefmt = "%a %d %b %Y %H:%M:%S"
formatter = logging.Formatter(fmt, datefmt)

# add handler and formatter to logger
fh.setFormatter(formatter)
logger.addHandler(fh)

# print log info
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')```

##### 文件配置
配置文件logging.conf如下:
```[loggers]
keys=root,example01

[logger_root]
level=DEBUG
handlers=hand01,hand02

[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0

[handlers]
keys=hand01,hand02

[handler_hand01]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stderr,)

[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=('log.log', 'a')

[formatters]
keys=form01,form02

[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s```

使用程序logger.py如下:
```#!/usr/bin/python
# -*- encoding:utf-8 -*-
import logging
import logging.config

logging.config.fileConfig("./logging.conf")

# create logger
logger_name = "example"
logger = logging.getLogger(logger_name)

logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')```

##### 字典配置
有兴趣的童靴可以使用```logging.config.dictConfig(config)```编写一个示例程序发给我,以提供给我进行完善本文。

#### 监听配置
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容