python logging模块的使用技巧
日志的级别:
- DEBUG
- INFO
- WARNNING
- ERROR
- CRITICAL
几个重要的概念
- Logger:记录器,是应用程序直接使用的借口
- Handler处理器,将(记录器)产生的日志记录发送往合适的借口
- 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的工作流程
-
- 由上图可以知道,如果使用者的代码中产生了日志提交,首先进行判断登记等级是否大于Logger实例的等价,如果小于,会抛弃这个日志,否则进入下一步.
-
- 创建日志,使用注册到Logger中的Filter进行过滤,轮流进行过滤,如果有一个把他过滤掉了,终止。否则等所有的过滤完成后进入下一步。
-
- 日子继续往下流
- 日志流向所有注册在Logger中的Handlers,首先判断等级够不够,接着判断有没有过滤器,都不能拒绝日志的话,将会格式化输出(会产生额外的信息,比如在哪个文件那一行等)。
-
- 判断日志能够进行传播,如果可以并且有父类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 |
一个例子
# -*- 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)```编写一个示例程序发给我,以提供给我进行完善本文。
#### 监听配置