2019/12/30 04-日志流、Formater、Filter

logging.info实际上真正工作的时候logger,跟logger是所有logger祖先,祖先下面可以产生一些logger,用工厂方法getlogger,会得到一个logger实例,getlogger()是拿到跟logger,得到跟logger两种方式(logging,root,getlogger()),logger就形成了体系结构,跟logger在最上面,就需要使用.点号父子关系\

在某一个logger调用info,就需要看这个logger对象的有效的level,如果大于等于这个有效level就可以输出日志,每一个logger都可以有自己的level,设定有效level就变成自己的,没设定就是用最近的父的
2019/12/30 04-日志流、Formater、Filter现在给了filename,控制台就不输出信息了,想要控制台也输出
2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
handler是控制信息输出的目的地,可以是控制台或者文件,handler(处理器),这个处理器可以有自己的level跟logger的level是两码事。
可以单独设置格式,可以设置过滤器。
logger是不干活的,真正干活的是handler,只不过有些时候忽略handler

2019/12/30 04-日志流、Formater、Filter
handler的继承
streamHandler 流式,默认把数据放到stderr,什么都不写,把数据输出到stderr
handler有两个子类,FileHandler文件(往文件写),_StderrHandler标准输出
日志输出其实都是handler做的,其实不是logger,logger应该有handler

2019/12/30 04-日志流、Formater、Filter
root应该有handler,而且不止一个,问root的handler=0,说明下面要做很多2019/12/30 04-日志流、Formater、Filter
跟logger也是logger2019/12/30 04-日志流、Formater、Filter
如果handler是none,stream和filename,在里面就抛出异常2019/12/30 04-日志流、Formater、Filter
如果handler是none,有一个在,就出问题
2019/12/30 04-日志流、Formater、Filter
if filename,代表filename不是空字符串,否则创建stream handler,root logger什么都没做都要生成rootloger,logger没有handler是不行的,就创建stream handler,就是把你的日志输出到控制台上去2019/12/30 04-日志流、Formater、Filter
streamhandler,默认显示红色的就是因为错误输出2019/12/30 04-日志流、Formater、Filter
filehandler继承自stream handler
2019/12/30 04-日志流、Formater、Filter
如果想要变成标准输出,把none改成sys.stdout即可2019/12/30 04-日志流、Formater、Filter
把参数中凑出一个handler,把handler扔到列表里去,把列表给了handlers
2019/12/30 04-日志流、Formater、Filter
handler我们能打印格式,handler被setFormatter,如果level不是none,就setlevel
2019/12/30 04-日志流、Formater、Filter
如果给的level不是none,就给一个不是root.level的级别2019/12/30 04-日志流、Formater、Filter
真正干活的是handler,但是handler可以单独设置level,可以单独设置格式(通过format产生),可以设置设置过滤器2019/12/30 04-日志流、Formater、Filter
现在生产的handler放到一个列表中,也就是这个列表里只有一个元素,如果 handlers不是none,就不创建(需要提供一个列表)2019/12/30 04-日志流、Formater、Filter
跟logger至少有一个handler
2019/12/30 04-日志流、Formater、Filter、没有handler但是确实能打印,就跟他的流有关系2019/12/30 04-日志流、Formater、Filter

创建的handler的初始的level是什么

2019/12/30 04-日志流、Formater、Filter
getlogger如果名字没有返回root,这个root就是rootlogger,否则就到.logger.manager里面2019/12/30 04-日志流、Formater、Filter
是把logger放到字典里通过名字来找2019/12/30 04-日志流、Formater、Filter
这就是实例化,logger类,创建出一个rv,然后往下加到字典中区2019/12/30 04-日志流、Formater、Filter创建出一个rv,然后往下加到字典中去2019/12/30 04-日志流、Formater、Filter
logger类里,要检查下你给的名词,checklevel,是否是合法范围,level的缺省值是NOTSET,没设定2019/12/30 04-日志流、Formater、Filter
一个logger在创建的过程中,默认创建的是0

rootlogger,这个level会在1731行改成warning
2019/12/30 04-日志流、Formater、Filter
logger在创建的时候,设定的level,默认是0,创建handler默认是空的,getlogger,这个logger对象,就需要创建这个logger对象,handlers是个空列条2019/12/30 04-日志流、Formater、Filter
handler没有,就可以用夫的,也可以不用2019/12/30 04-日志流、Formater、Filter下面创建一个filehandler,addhandler,给空列条塞一个handler进去
2019/12/30 04-日志流、Formater、Filter
上面是streamhandler,下面是加了一个filehandler2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
handler没指定格式
2019/12/30 04-日志流、Formater、Filter
说明,格式就是%(message)s,现在既可以在控台输出,又可以文件里输出2019/12/30 04-日志流、Formater、Filter
现在handler级别没设定2019/12/30 04-日志流、Formater、Filter
line2按照集成线路走到filehandler里了,这条数据又到了streamhandler里面 了2019/12/30 04-日志流、Formater、Filter
没有filehandler就没有文件,但是在streamhandler里有
2019/12/30 04-日志流、Formater、Filter
执行一下看看,2019/12/30 04-日志流、Formater、Filter
没有输出因为是w,w一下会把文件清空
2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
这样就有了
2019/12/30 04-日志流、Formater、Filter
也就是handler有自己的level
但是logger也有自己的level

2019/12/30 04-日志流、Formater、Filter

日志流

2019/12/30 04-日志流、Formater、Filter
logger的level,自己设定就拿自己的,不然就从最近的父的拿
s . s1多了空格没有父子关系了
2019/12/30 04-日志流、Formater、Filter
现在就有父子关系了
2019/12/30 04-日志流、Formater、Filter
日志在哪个logger产生,就需要先过自己的一关
2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter

继承关系及信息传递

logger日志想流进来,首先在哪个logger产生,就要在哪个logger级别进行对比,如果这个门槛太高,信息就进不来,
2019/12/30 04-日志流、Formater、Filter
如果没有设置就用最近的父,root默认在1731行死warning
2019/12/30 04-日志流、Formater、Filter

流转过程很重要

2019/12/30 04-日志流、Formater、Filter
产生消息的级别,就要和当前logger的Effectivelevel有效级别进行比较,如果低于当前logger的有效等级,就流程结束(自己这关都过不了),否则就生成log记录。
2.这个记录会交给当前logger的所有handler处理

log1下面有三个handler,handler默认几倍是noset=0,,所以这个消息先对比log1等级,然后转发给三个handler进行比较,handler级别如果高于消息的级别,handler就对这个记录没有反应
2019/12/30 04-日志流、Formater、Filter
当前logger的所有handler处理完,就要看自己的propagate属性,如果是True表示向父logger传递这个日志记录,否则到此流程结束,(这个就是开关)
2019/12/30 04-日志流、Formater、Filter
如果日志记录传递到了父logger,不需要和父logger的level比较,而是直接交给父的所有handler,父logger成为当前logger。重复2、3步骤,直到当前logger的父logger是None退出(最后跑到rootlogger),也就是说当前logger最后一般是root logger(是否能到root logger要看中间logger是否允许propagate)
2019/12/30 04-日志流、Formater、Filter
按照道理,log1传递给了error就看不到了,说明没有跟logging.error比较2019/12/30 04-日志流、Formater、Filter
这个函数创建了一个handler列表
2019/12/30 04-日志流、Formater、Filter
查看logger类
2019/12/30 04-日志流、Formater、Filter
也就是用getlogger取到的,propagate=TRUE,默认都有传递行为,都会向父一级进行传递2019/12/30 04-日志流、Formater、Filter
这样就传不到root上去 了
2019/12/30 04-日志流、Formater、Filter
logger实例初始的propagate属性为true,即允许向父logger传递消息2019/12/30 04-日志流、Formater、Filter
如果root没有handler,就默认创建一个StreamHandler,如果设置了filename,就创建一个FileHandler。如果设置了format参数,就会用它生成一个formatter对象,并把这个formatter加入到刚才创建的handler上(没有设置format参数,就会自己创建一个,只不过就一个message),然后把这些handler加入到root.handlers列表上。level是设置给root logger的。
如果root.handlers列表不为空,logging.basicConfig的调用什么都不做。

2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
要是没有这句话,root都没有handler2019/12/30 04-日志流、Formater、Filter
这样就没有handler,没有handler就什么都没打印出来
2019/12/30 04-日志流、Formater、Filter

日志流转图

2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
日志信息来跟logger的level进行比较,,不能通过就stop,可以就创建一个日志记录2019/12/30 04-日志流、Formater、Filter
日志记录就需要过滤,过滤不通过结束,通过,向下,reject是反义的
2019/12/30 04-日志流、Formater、Filter
如果这个日志记录通过自己logger的level,然后pass to到current logger,给当前logger的所有handler发送,所有handler处理完,把这些handler都遍历完以后,就继续向下做,问是否需要传递,不传递就结束了,传递就传递给自己的parent logger父logger,如果没有父logger就结束,有自己的父logger就将当前logger设定自己的parent2019/12/30 04-日志流、Formater、Filter
这样parent就设定成自己的当前logger了,发给当前logger的handler,不跟有效level比较了
2019/12/30 04-日志流、Formater、Filter
接写来时发给handler的整个过程,把记录发给handler,handler把这个记录跟自己的level进行比较,不合适就stop,yes就到了过滤器,过滤不成功stop,yes就向后继续跑
2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
c就是current,如果propagate时true,就进不来这里,等于none就不进循环了2019/12/30 04-日志流、Formater、Filter
遍历handler,拿handler的level和你日志记录的level进行比较2019/12/30 04-日志流、Formater、Filter
这是logger的2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
将root定义INFO级别,格式如下
2019/12/30 04-日志流、Formater、Filter
root重新设定级别到error
2019/12/30 04-日志流、Formater、Filter
准备创建一个streamhandler,默认是到stderr
2019/12/30 04-日志流、Formater、Filter
两个handler,打印出来是不一样的,2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
两次就发生变化了
一个级别没设定,一个级别被修改成了warning,这是handler的级别,不是root.logger的级别
2019/12/30 04-日志流、Formater、Filter
打印不出来信息,查看当前有效level2019/12/30 04-日志流、Formater、Filter
注释掉临时设定的error,就打印一条,下面的还是过不去2019/12/30 04-日志流、Formater、Filter
改成warning就能出现两条信息,没设定handler,默认就打印message
2019/12/30 04-日志流、Formater、Filter
缺省的root,一样可以捆绑多个handler,它给自己创建一个默认stream,也可以添加一个filehandler
2019/12/30 04-日志流、Formater、Filter
查看下面这一段2019/12/30 04-日志流、Formater、Filter
创建一个log1 logger对象,添加一个handler,里面就一个handler
2019/12/30 04-日志流、Formater、Filter
继续下面一段
2019/12/30 04-日志流、Formater、Filter
log3中没有handler,warning消息到达log2,log2的logger的level无效,看handler的等级,也就是test.log文件里应该有数据
2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
没有设定propagate,继续向后传,s的handler还是warning也会往test.log文件里面写,所以消息就有两条,也可以给这两个设定不同的format对象2019/12/30 04-日志流、Formater、Filter
看到三个stderr,下面的是h0打 的,上面是root打的2019/12/30 04-日志流、Formater、Filter
Formatter是一个类,允许指定某个格式的字符串,如果是none就打印message2019/12/30 04-日志流、Formater、Filter
会root缺省的streamhandler定义的格式
2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
这时候把格式送给h22019/12/30 04-日志流、Formater、Filter
等于logging下面有Formatter类
2019/12/30 04-日志流、Formater、Filter
**再运行一次,每一个handler都可以设定level,每个handler都可以设定自己的format
**
2019/12/30 04-日志流、Formater、Filter
addhandler,表示handler可以往容器里加,而setformatter只能再handler上加一次

filter

filter可以增加过滤器,过滤器之后影响某一个handler,不会影响整个处理流程,但是,如果过滤器加到logger上,就会影响流程
2019/12/30 04-日志流、Formater、Filter
这个跟logger相关的filter如果过不起,就到不了handler,
logger的filter通不过,就没有后面的流转了
2019/12/30 04-日志流、Formater、Filter
每一个handler里面是可以在家filter,handler可以给自己加level,format,filter
2019/12/30 04-日志流、Formater、Filter
再h2上加了个filter,h2是再log2上面的,也就是只影响log2下的h2的过滤2019/12/30 04-日志流、Formater、Filter
先跟level比较,比完了再跟filter比较2019/12/30 04-日志流、Formater、Filter
传递过来就需要所有的handler来过滤,所以handler的filter就起作用了2019/12/30 04-日志流、Formater、Filter
这个过滤器就会判断下,这个过滤器是谁,是s开头的所有日志信息的,因为这是跟s相关的所有logger产生的2019/12/30 04-日志流、Formater、Filter
消息产生后,会有s.s1的名字,这个名字就可以过滤2019/12/30 04-日志流、Formater、Filter
在现在这个记录当中去kan 's’这个名字,从0开始到name的长度!=0(在一个字符串中,从头定死开始找,)
2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
从0开始找第一个字符,如果第一个字符能够找到就行,find不会抛出异常,找不到了-1,找不到爱什么是什么,(找到的索引值之能是0,所以!=0)2019/12/30 04-日志流、Formater、Filter
这两句相等
2019/12/30 04-日志流、Formater、Filter
如果用log2发出的记录的日志,都是s.s1,在过这个过滤器的时候,是可以通过的
2019/12/30 04-日志流、Formater、Filter2019/12/30 04-日志流、Formater、Filter
filter用的较少

2019/12/30 04-日志流、Formater、Filter
logging模块,有几个有难点,有效级别,handler(handler可以有自己的format,filter,level)
如果偷懒每个logger都不用了,直接所有模块都是logging.,不偷懒,就是logging.getlogger(name)拿这个模块名创建一个当前的独自的logger,一般更多是把数据发到file当中去