logging模块经常使用,必须掌握(threading,multiprocessing,concurrent.futures都需要会)
日志的流转过程,以前的所有疑问都可以在这里找到解答
日志该如何写到控制台或者文件,能否进行过滤和限制
python必用模块,日志分析可以多线程,多进程,大数据,就是分布式进程,要做日志分析,输出日志是很重要的东西,日志是分级别的
没设置,级别数值就是0
可以给11,但是不对应INFO和DEBUG,哪个都不对应,代表比DEBUG高一点点,可以理解左边都是常量,
要求每一条日志的紧要程度。大于等于你设定的级别,是可以输出的,如果是小于的就不允许输出
测试一下
假设设置级别是INFO,
红色其实是stderror
deubug信息低于info,打印不出来
这些就是定义的常量,全部大写
相当于写20
15还是不行
9就有debug了
大于等于消息就通过,所有的日志消息都是有级别的
如果把debug打开,可能对于程序要显示太多信息了。文本是比较占空间的,日志文件可能有几百G,但是压缩后可能就几兆了,如果要详细点的就用DEUBUG
如果一般的就用INFO,一般性信息
d前面必须是个整数,字符串后面就应该有s
一般都是先转换成数字然后再转换成字符串输出,
threadName和processName需要注意小驼峰
常用的asctime,
日志信息在哪个函数中调用
只有threadName,processName,funcName,要大写,其他不用大写
告诉你级别是什么
产生日志的行号,,行号可以快速定位到源代码的哪一行
信息,必须给
logger调用的名字
打印logger看看,root是根,现在打印信息都是用根logger打印的
一般关心如下数据,就足够定位问题了
就这几个是小驼峰,其他都是小写
15是占位,-负是方向,向左跑(左对齐),坐标系,负数再左边
format一放,默认输出是warning
现在选中的整体是一个参数,对于warning来讲,接收了一个实参,因为这个实参是format函数的返回值
有两种方式传数据,一个是单一字符串的,还有种就是c风格的
没有message要日志是没有用的,记录的目的就是记录message
message就是info的第一参数
作为一个实参传给info
还有一种c风格的,这样等于传了两个参数,
不用c风格,就只能写一个参数
这个相当于把123 转换成str
本身就是数字没问题
没有权利把字符串转换成数字
c风格,可以记,但不做强制性要求
这就是定义的格式,但是message习惯放最后
扩展信息
、自定义报错
这时候就要替school传参,应该是要变成可索引的东西
这样就成了
这样就向右了
一般数据和数据用\t,数据内部用空格
现在想把日期改改样子
日期格式最好提供你所方便处理的日期格式
open函数有mode
可以输出到文件
再次执行
一般日志用的追加方式,是aw,现在改成w,就是覆盖了重写了
当你设置filename之后,原来再控制台打印,写到文件里了
filename设置日志文件,filemode设置读写模式,open怎么写,这里怎么写
logger模块在加载的时候会创建一个root logger,不管写什么都会创建根logger,根logger对象的默认级别是WARNING
在1731行,__init__py,说明这个是logging模块(包)的顶层代码里的写的root,只要包加载了,root就加载了
只要加载了logging模块,就会创建一个root logger,可以调用,logging.basicConfig来调整级别,
当前是root。logger,现在的级别是debug=10,basicConfig就是在做跟logger的定义
用logging.info打印其实是用的根logger在打印,跟logger还有一些默认行为,跟logger如果没设定filename,默认向控制台输出,设定filename,就跑到你指定的文件里了
调用这个logging.info实际是调用跟logger的info
如果想要自定义创建格式,不想用rootlogger
创建一个logger,这是一个工厂方法,问logging工厂要,给一个logger实例,就会给你一个logger实例
每一个logger都会有名字,logging里面有全局变量root
名字一样,id一样
当什么都不写返回的是root
给个名字就不是同一个东西了,也就是现在提供一个名字,它会用这个名字创建一个logger实例,什么都没给返回根logger,如果给名字,就是创建一个新的跟logger对象
跟logger对象和创建的新的logger对象,多少有点关系
再次要了一次同名logger,名字一样返回的是同一个实例
要求使用工厂方法,从里面获取一个logger对象出来,如果这个logger对象已经存在则直接返回,不返回就创建并返回。
什么都不写返回的是跟logger
logger是层次结构,使用.点号分割,如‘a’、‘a.b’,a.b的父是a,a.b.c.d的父应该是a.b.c
跟logger和s是有关系的,就是一个父子关系
跟下面有s,s下面有s.s1
logging模块加载必须有跟,这样创建其他logger都是从根开始,是所有其他logger的祖先
一般写喜欢这么写,if name==‘main’,这个是模块名的,一般自己写的.py文件就是模块,在这模块中没必要创建两个logger对象,创建一个就行,(起名字,最偷懒的就是用当前模块名)
父子关系得用.点号
这样换成实例即可,logging,归根到底还是logger在做
一般都这么用
跟是所有的父,模块名是logger
调整到warning就输出不了了
logging的流控制比你想象的复杂,是0还输出不出来
geteffective有效的level
现在就不管父的level了,就是自己设定的了,如果没有设定,感觉像从父类继承下来的,有效 level可以理解为是一个继承关系
现在就没打印出来
18就打印出来了
CRITICAL最高到50了
自己有什么用自己的,自己没有从父的来,父的没有才能到祖先
现在把跟level相关设定去掉,现在就全是30了,这个level设定,是在logger上
讲到handler logger的时候跟这个就无关,这个是跟父子logger有关的
我们讲的是logger树,是从跟logger开始,logger上面的level有继承关系,都是要看有效level,自己设定用自己的,没有设定就用跟logger的,找最近父的,找到离自己最近level作为有效level
拿到跟logger两种方法。logging.root或者logging.getLogger(),设定了level,所以受有效level影响
每一个logger对象,创建后,都有一个等效level,等效level才会真正决定输出的东西,每一次输出的时候会看当前的动态有效level是什么