日志级别level | 数值 |
---|---|
CRITICAL | 50 |
ERROR | 40 |
WARNING | 30 ,默认日志级别 |
INFO | 20 |
DEBUG | 10 |
NOTSET | 0,表示不设置 |
日志级别是指产生日志的严重程度
设置一个级别后,严重程度低于次级别的日志消息将会被忽略
数字越高,优先级别越高 python
#!/usr/bin/python3.6 #conding:utf-8 import threading import time import logging logging.basicConfig(level=logging.INFO) #设置日志级别为info def add(x,y): logging.warning(x+y) # 此处定义的日志级别是warning,所以可以被打印出来,默认的日志打印格式是 级别:用户:信息 t=threading.Timer(1,add,args=(3,4)) # 此处表示6秒后出结果 t.start()
结果以下安全
默认的日志打印格式是级别:用户:信息ide
属性名 | 格式 | 描述 |
---|---|---|
日志消息内容 | %(message)s | 当调用formatter.format() 时设置 |
asctime | %(asctime)s | 建立logrecord时的可读时间,默认格式是Y-m-d H:M:S, (逗号后面的数字是毫秒部分的时间) |
函数名 | %(funcName)s | 日志调用所在的函数名 |
日志级别名称 | %(levelname)s | 消息级别名称,DEBUG,INFO,WARNING,ERROR,CRITICAL |
日志级别数值 | %(levelno)s | 消息的级别数字DEBUG,INFO,WARNING,ERROR,CRITICAL |
行号 | %(lineno)d | 日志调用所在源码行号 |
模块 | %(module)s | 模块(filename的名字部分) |
进程ID | %(process)d | 进程ID |
线程ID | %(thread)d | 线程ID |
进程名称 | %(processName)s | 进程名 |
线程名称 | %(threadName)s | 线程名字 |
d 格式化成数字,s格式化成字符串 函数
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)-15s\tThread Name: %(threadName)s\t%(message)s" # 此处定义日志格式 import logging logging.basicConfig(level=logging.INFO,format=FORMAT) #设置日志级别为info,此处format为引用日志格式 def add(x,y): logging.warning(x+y) # 此处定义的日志级别是warning,所以可以被打印出来 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
结果以下 线程
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)-15s\tThread Name: %(threadName)s\t%(message)s" # 此处定义日志格式 import logging logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt='%y-%m-%d %H:%M:%S %z') #设置日志级别为info,此处format为引用日志格式,此处经过定义日志格式来 # 肯定打印的日志为正常格式,其和%(asctime)互相做用 def add(x,y): logging.warning(x+y) # 此处定义的日志级别是warning,所以可以被打印出来 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
结果以下 debug
不一样打印风格日志
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)-15s\tThread Name: %(threadName)s\t%(message)s" # 此处定义日志格式 import logging logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt='%y-%m-%d %H:%M:%S %z') #设置日志级别为info,此处format为引用日志格式,此处经过定义日志格式来 # 肯定打印的日志为正常格式,其和%(asctime)互相做用 def add(x,y): logging.warning("%d",x+y) # 此处定义的日志级别是warning,所以可以被打印出来,此处是c风格处理日志 logging.info("{} 值为 {}".format(threading.enumerate(),x+y)) # 此处是format方式处理 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
打印结果以下 code
定义一个新的变量来进行存储 orm
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)s \t threadName: %(threadName)s \t %(message)s \t %(myname1)s" # 此处定义日志格式,此处定义变量名为myname import logging logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt='%y-%m-%d %H:%M:%S %z') #设置日志级别为info,此处format为引用日志格式,此处经过定义日志格式来 # 肯定打印的日志为正常格式,其和%(asctime)互相做用 d={"myname1":"zhangsan"} #此处定义变量值为zhangsan,是字典格式 def add(x,y): logging.warning("%d",x+y,extra=d) # 此处定义的日志级别是warning,所以可以被打印出来,此处是c风格处理日志,经过此处引用extra 字典获得结果 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
结果以下 对象
#!/usr/bin/python3.6 #conding:utf-8 import threading import time FORMAT="%(asctime)s \t threadName: %(threadName)s \t %(message)s \t %(myname1)s" # 此处定义日志格式,此处定义变量名为myname import logging logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt='%y-%m-%d %H:%M:%S %z',filename='/root/test.log') #设置日志级别为info,此处format为引用日志格式,此处经过定义日志格式来 # 肯定打印的日志为正常格式,其和%(asctime)互相做用,此处指定打印的路径,若不存在,则建立并追加,如此下面便不会再次打印 d={"myname1":"zhangsan"} #此处定义变量值为zhangsan,是字典格式 def add(x,y): logging.warning("%d",x+y,extra=d) # 此处定义的日志级别是warning,所以可以被打印出来,此处是c风格处理日志,经过此处引用extra 字典获得结果 t=threading.Thread(target=add,args=(3,4),name='a1') t.start()
结果以下
其至关于输出重定向到文件
使用工厂方法返回一个logger实例。
logger.getLogger([name=None)]
指定name,返回一个名称为name的Logger实例,若是再次使用相同的名字,是实例化一个对象。
未指定name,则返回logger实例,名称是root。及根Logger
Logger 是层次结构的,使用. 点号分割。如'a',或'a.b'或'a.b.c.d',a是a.b的父parent,a.b是a的子child,对于foo来讲,名字为foo.bar,foo.bar.baz,foo.bam都是foo的后代。
#!/usr/bin/python3.6 #conding:utf-8 import logging log=logging.getLogger() print (log.name) #打印当前实例的名称,其默认名称为root print (type(log))# 打印当前实例的类型
结果以下
#!/usr/bin/python3.6 #conding:utf-8 import logging log=logging.getLogger('a') # 此处定义其名称, print (log.name) #打印当前实例的名称 print (log,type(log))# 打印当前实例的类型和实例状况
结果以下
#!/usr/bin/python3.6 #conding:utf-8 import logging #!/usr/bin/poython3.6 #conding:utf-8 import logging root=logging.getLogger() print (root,id(root)) # 此处返回跟和跟地址 log=logging.getLogger('a') # 此处定义其名称, print (log.name) #打印当前实例的名称 print (log,type(log),log.parent,id(log),id(log.parent))# 打印当前实例的类型和实例状况及其父类状况,此处打印当前给状况和父根状况 # log1=logging.getLogger('a.b') print (log1.name) print (log1,type(log1),log1.parent,id(log1.parent))# 此处打印当前根父跟状况
结果以下
上述代表,其a.b的父类是a,a的父类是root ,其直接存在父子级别
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.INFO,datefmt='%Y-%m-%d %H:%M:%S',format=FORMAT) root=logging.getLogger() root.warning('my root') log=logging.getLogger('a') # 此处定义其名称, log.warning('my log') log1=logging.getLogger('a.b') log1.warning('my log1')
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.INFO,datefmt='%Y-%m-%d %H:%M:%S',format=FORMAT) root=logging.getLogger() print (root,id(root)) root.warning('my root') loga=logging.getLogger(__name__) # 此处使用模块名称进行定义名字 print (loga,id(loga),loga.name) loga.warning('my loga')# loga.name 也不能在此中打印出来 logb=logging.getLogger("{}.{}".format(__name__,'abcd')) # 此处使用模块名称下的具体方法定义名称,经过format进行字符串的拼接 print (logb,id(logb),logb.name) logb.warning('my logb') # logb.name不能打印出来
结果以下
获取和设置相关级别
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.INFO,datefmt='%Y-%m-%d %H:%M:%S',format=FORMAT) root=logging.getLogger() print (root,id(root)) print (root.getEffectiveLevel())#此处打印日志级别 loga=logging.getLogger(__name__) # 此处使用模块名称进行定义名字 loga.warning('my loga')# loga.name 也不能在此中打印出来 print (loga.getEffectiveLevel())#此处打印日志级别 logb=logging.getLogger("{}.{}".format(__name__,'abcd')) # 此处使用模块名称下的具体方法定义名称,经过format进行字符串的拼接 logb.warning('my logb') # logb.name不能打印出来 logb.debug('my debug') # 此处的debug日志将不能被打印出来 print (logb.getEffectiveLevel()) #此处打印日志级别
结果以下
修改日志级别并进行配置和获取
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.INFO,datefmt='%Y-%m-%d %H:%M:%S',format=FORMAT) root=logging.getLogger() print (root,id(root)) print (root.getEffectiveLevel())#此处打印日志级别 loga=logging.getLogger(__name__) # 此处使用模块名称进行定义名字 loga.info('my loga')# loga.name 也不能在此中打印出来 print (root.getEffectiveLevel())#此处打印日志级别 print (loga.getEffectiveLevel())#此处打印日志级别 loga.setLevel(28)# 此时日志级别位于INFO 和 WARNING之间, print (loga.getEffectiveLevel()) # 获取修改后的日志级别 print ('+'*20,'logb') logb=logging.getLogger("{}.{}".format(__name__,'abcd')) # 此处使用模块名称下的具体方法定义名称,经过format进行字符串的拼接 logb.info('my logb') # 此处由于自身没有配置日志级别,所以继承了上面的日志级别,所以,其不能打印 logb.setLevel(10) logb.info('my logb') # 此处由于自身设置了日志级别,所以其能够打印 logb.warning('my debug') print (logb.getEffectiveLevel()) #此处打印日志级别
结果以下
全局能够设定,但本身模块能够根据本身的状况进行调整和修改
上述用于设置模块和模块对应函数或类的日志级别,经过上述的定义能够肯定打印日志的级别和相关的配置状况
向在模块级别的进行配置和修改日志的级别设置
想作个性化比较难
重要的主要是level和format 的状况
handler 控制日志信息的输出目的地,能够是控制台,文件
能够单独设置level
能够单独设置格式
能够设置过滤器
handler分为
1 StreamHandler # 不指定使用sys.stderr
A FileHandler # 文件输出
B _StderrHandler # 标准输出
2 NullHandler # 什么都不作Handler父类 ,FileHandle和_StderrHandler和NullHandler是子类,子类能够继承父类的相关属性
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此处实例化出来一个对象 log1.setLevel(logging.WARNING) #设置此对象的相关属性 h1=logging.StreamHandler() # 实例化一个标准输出的handler h1.setLevel(logging.INFO) # 设置handler的级别 log1.addFilter(h1) # 将h1加入到log1 log1.info('info log1') # 打印INFO日志。 log1.warning('warning log1') # 打印WARING ,此处只能打印WAENING
结果以下
此处代表,虽然handler设置了info级别,但其没不能影响log1的设置,仍然不能打印info级别
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此处实例化出来一个对象 log1.setLevel(logging.INFO) #设置此对象的相关属性 h1=logging.StreamHandler() # 实例化一个标准输出的handler h1.setLevel(logging.ERROR) # 设置handler的级别 log1.addFilter(h1) # 将h1加入到log1 log1.warning('warning log1') # 打印WARING ,此处只能打印WAENING log1.info('info log1') log2=logging.getLogger('s.s1') #此处继承了s1的属性 print (log2.getEffectiveLevel()) log2.warning('wangring log2') #此处设置的warning 和handler中设置的ERROR不冲突,由于ERROR 不针对当前设置
结果以下
此处虽然handler设置了ERROR 级别,但info级别仍是可以打印出来,其不会影响当前级别的日志,而继承的日志也没受到handler的影响直接打印
日志输出到文件
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此处实例化出来一个对象 log1.setLevel(logging.INFO) #设置此对象的相关属性 h1=logging.FileHandler('/root/test1.log') # 实例化一个文件输出的handler h1.setLevel(logging.ERROR) # 设置handler的级别 log1.addHandler(h1) # 将h1加入到log1 log1.warning('warning log1') # 打印WARING ,此处只能打印WAENING log1.info('info log1') log1.error('error log1') #打印error级别
结果以下
文件中结果以下
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此处实例化出来一个对象 log1.setLevel(logging.WARNING) #设置此对象的相关属性 h1=logging.FileHandler('/root/test1.log') # 实例化一个文件输出的handler h1.setLevel(logging.INFO) # 设置handler的级别 log1.addHandler(h1) # 将h1加入到log1 log1.warning('warning log1') # 打印WARING ,此处只能打印WAENING log1.info('info log1')
结果以下
文件结果
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此处实例化出来一个对象 log1.setLevel(logging.WARNING) #设置此对象的相关属性 h1=logging.FileHandler('/root/test1.log') # 实例化一个文件输出的handler h1.setLevel(logging.INFO) # 设置handler的级别 log1.addHandler(h1) # 将h1加入到log1 log1.warning('warning log1') # 打印WARING ,此处只能打印WAENING log1.info('info log1') log2=logging.getLogger('s.s1') print (log2.getEffectiveLevel()) log2.info('log2 info')
文件结果
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此处实例化出来一个对象 log1.setLevel(logging.INFO) #设置此对象的相关属性 h1=logging.FileHandler('/root/test1.log') # 实例化一个文件输出的handler h1.setLevel(logging.INFO) # 设置handler的级别 log1.addHandler(h1) # 将h1加入到log1 log1.warning('warning log1') # 打印WARING ,此处只能打印WAENING log1.info('info log1') log2=logging.getLogger('s.s1') print (log2.getEffectiveLevel()) log2.info('log2 info')
结果
文件结果
#!/usr/bin/python3.6 #conding:utf-8 import logging FORMAT="%(asctime)s Threadinfo: %(threadName)s %(message)s" logging.basicConfig(level=logging.INFO,format=FORMAT) log1=logging.getLogger('s') #此处实例化出来一个对象 log1.setLevel(logging.INFO) #设置此对象的相关属性 h1=logging.FileHandler('/root/test1.log') # 实例化一个文件输出的handler h1.setLevel(logging.INFO) # 设置handler的级别 fmtr=logging.Formatter("%(asctime)s Threadinfo: %(threadName)s %(message)s %(thread)s") h1.setFormatter(fmtr) log1.addHandler(h1) # 将h1加入到log1 log1.warning('warning log1') # 打印WARING ,此处只能打印WAENING log1.info('info log1') log2=logging.getLogger('s.s1') print (log2.getEffectiveLevel()) log2.info('log2 info')
结果以下
文件结果以下
import logging root=logging.getLogger() root.setLevel(logging.ERROR) print ('root',root.handlers) #打印handler列表 h0=logging.StreamHandler() h0.setLevel(logging.WARNING) root.addHandler(h0) print ('root',root.handlers) # 打印列表 for h in root.handlers: print ("root handler = {} ,formatter= {}".format(h,h.formatter)) # 打印默认的formatter
结果以下
import logging root=logging.getLogger() root.setLevel(logging.ERROR) print ('root',root.handlers) #打印handler列表 h0=logging.StreamHandler() h0.setLevel(logging.WARNING) root.addHandler(h0) print ('root',root.handlers) # 打印列表 for h in root.handlers: print ("root handler = {} ,formatter= {}".format(h,h.formatter)) # 打印默认的formatter log1=logging.getLogger('s') log1.setLevel(logging.ERROR) h1=logging.FileHandler('/root/test2.log') log1.addHandler(h1) print ('log1',log1.handlers) log2=logging.getLogger('s.s1') log2.setLevel(logging.CRITICAL) h2=logging.FileHandler('/root/test2.log') h2.setLevel(logging.WARNING) print ('log2 formatter',h2.formatter) # handler 默认无Formatter f2=logging.Formatter("log2 %(name)s %(asctime)s %(message)s") h2.setFormatter(f2) print ('log2.formatter',h2.formatter) log2.addHandler(h2) print ('log2',log2.handlers)
结果为
文件结果为
1 每个logger实例的level如同入水口,让水流进来,若是这个门槛过高,水流就不能进来,其相关低级别的信息必定不能被打印出来
2 若是level没有设置,则使用父类logger的,若是父类没有,则继续寻找父类的,最终找到root,而root的默认设置是WARNING
3 消息传递流程
在某个logger上产生某种级别的消息,首先和logger的level检查,若是消息level低于logger的EffectiveLevel有效级别,则丢弃消息,若是经过(大于等于)检查后,消息交给全部的handler处理,每个handler须要和本身的level比较来决定是否处理,若是没有一个handler,或者消息已经被处handler处理过了,则须要经过本logger的propagate属性是不是True,True则会把这个消息继续传递给父logger,父logger成为新的logger。新的logger直接把消息交给新的logger的全部handler,handler都处理完了,若是paragate属性是True,新的logger的父成为新的logger,它的全部handler处理消息。
4 logger 实例初始化的paragate属性为True,及容许向父传递logger消息
5 logging.basicConfig
若是root没有handler,就默认建立一个StreamHandler ,若是设置了filename,则就建立了一个FileHandler,若是设置了format参数,它就会生成一个formatter对象,并把这个formatter加入到刚才建立的handler上,而后把这些handler加入到root.handlers列表上,level是设置给root logger的。若是root.handlers列表不是空,则logging.basicConfig的调用什么都不作。
能够为handler增长过滤器,因此过滤器只影响某一个handler,不会影响整个处理流程
import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.ERROR,format=FORMAT,datefmt="%y-%m-%d %H:%M%S %z") #从新格式化传值,定义日志输出到文件 root=logging.getLogger() print (root,id(root)) loga=logging.getLogger('s') # 模块和模块下的某个函数或类 print (loga,id(loga),id(loga.parent)) loga.setLevel(logging.INFO) print (loga.getEffectiveLevel()) #默认对应的是常量20 hadr=logging.FileHandler('/root/loga.txt') # 定义,不指定则是标准错误输出 hadr.setLevel(logging.INFO) fmtr=logging.Formatter("%(asctime)s %(thread)d %(threadName)s %(message)s") #此处是一个实例。此处能够本身定义 hadr.setFormatter(fmtr) fltr=logging.Filter('s') # 此处设置过滤器为s,则为s,s.s1都可经过 hadr.addFilter(fltr) loga.addHandler(hadr) logb=logging.getLogger('s.s1') logb.getEffectiveLevel() logb.info('logb info')
结果以下
文件结果以下
import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.ERROR,format=FORMAT,datefmt="%y-%m-%d %H:%M%S %z") #从新格式化传值,定义日志输出到文件 root=logging.getLogger() print (root,id(root)) loga=logging.getLogger('s') # 模块和模块下的某个函数或类 print (loga,id(loga),id(loga.parent)) loga.setLevel(logging.INFO) print (loga.getEffectiveLevel()) #默认对应的是常量20 hadr=logging.FileHandler('/root/loga.txt') # 定义,不指定则是标准错误输出 hadr.setLevel(logging.INFO) fmtr=logging.Formatter("%(asctime)s %(thread)d %(threadName)s %(message)s") #此处是一个实例。此处能够本身定义 hadr.setFormatter(fmtr) fltr=logging.Filter('s') # 此处设置过滤器为s,则为s,s.s1都可经过 hadr.addFilter(fltr) loga.addHandler(hadr) loga.info('loga info') logb=logging.getLogger('s.s1') logb.getEffectiveLevel() logb.info('logb info') logc=logging.getLogger('s.s1') logc.getEffectiveLevel() logc.info('logc info')
结果以下
文件以下
import logging FORMAT="%(asctime)s %(thread)d %(message)s" logging.basicConfig(level=logging.ERROR,format=FORMAT,datefmt="%y-%m-%d %H:%M%S %z") #从新格式化传值,定义日志输出到文件 root=logging.getLogger() print (root,id(root)) loga=logging.getLogger('s') # 模块和模块下的某个函数或类 print (loga,id(loga),id(loga.parent)) loga.setLevel(logging.INFO) print (loga.getEffectiveLevel()) #默认对应的是常量20 hadr=logging.FileHandler('/root/loga.txt') # 定义,不指定则是标准错误输出 hadr.setLevel(logging.INFO) fmtr=logging.Formatter("%(asctime)s %(thread)d %(threadName)s %(message)s") #此处是一个实例。此处能够本身定义 hadr.setFormatter(fmtr) fltr=logging.Filter('a') # 此处设置过滤器为s,则为s,s.s1都可经过 hadr.addFilter(fltr) loga.addHandler(hadr) loga.info('loga info') logb=logging.getLogger('s.s1') logb.getEffectiveLevel() logb.info('logb info') logc=logging.getLogger('s.s1') logc.getEffectiveLevel() logc.info('logc info')
文件以下
消息loga,它的名字是's',所以过滤器名字设置为s,则s.s1,s.x和s都能经过,但其余的则不能经过,不设置过滤器名字,全部消息都能经过,设置为a,则和s,s.s1和s.s2无任何关系,所以其不能使用,实例对象只有一个,一旦同名,也是只有一个,线程的不安全不会影响logging,只会影响print。