python美化输出模块_python日志处理模块

一 日志处理模块概述

1 日志级别

日志级别level

数值

CRITICAL

50

ERROR

40

WARNING

30 ,默认日志级别

INFO

20

DEBUG

10

NOTSET

0,表示不设置

日志级别是指产生日志的严重程度

设置一个级别后,严重程度低于次级别的日志消息将会被忽略

数字越高,优先级别越高

#!/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()

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

默认的日志打印格式是级别:用户:信息

2 格式字符串

1 常见格式

属性名

格式

描述

日志消息内容

%(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()

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

2 格式化时间字串

#!/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()

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

不同打印风格

#!/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()

打印结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

3 新变量处理

定义一个新的变量来进行存储

#!/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()

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

4 输出到文件

#!/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()

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

其相当于输出重定向到文件

二 logger 类

1 概述

使用工厂方法返回一个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的后代。

2 基本实验

1 打印空name的logger

#!/usr/bin/python3.6

#conding:utf-8

import logging

log=logging.getLogger()

print (log.name) #打印当前实例的名称,其默认名称为root

print (type(log))# 打印当前实例的类型

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

2 打印非空name的logger

#!/usr/bin/python3.6

#conding:utf-8

import logging

log=logging.getLogger('a') # 此处定义其名称,

print (log.name) #打印当前实例的名称

print (log,type(log))# 打印当前实例的类型和实例情况

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

3 打印层次化logger

#!/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))# 此处打印当前根父跟情况

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

上述表明,其a.b的父类是a,a的父类是root ,其直接存在父子级别

4 继承和重用

#!/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')

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

5 规范化定义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))

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不能打印出来

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

6 获取和修改日志级别

获取和设置相关级别

#!/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()) #此处打印日志级别

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

修改日志级别并进行配置和获取

#!/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()) #此处打印日志级别

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

7 总结:

全局可以设定,但自己模块可以根据自己的情况进行调整和修改

上述用于设置模块和模块对应函数或类的日志级别,通过上述的定义可以确定打印日志的级别和相关的配置情况

向在模块级别的进行配置和修改日志的级别设置

想做个性化比较难

重要的主要是level和format 的情况

2 handler

1 概述

handler 控制日志信息的输出目的地,可以是控制台,文件

可以单独设置level

可以单独设置格式

可以设置过滤器

handler分为

1 StreamHandler # 不指定使用sys.stderr

A FileHandler # 文件输出

B _StderrHandler # 标准输出

2 NullHandler # 什么都不做

Handler父类 ,FileHandle和_StderrHandler和NullHandler是子类,子类可以继承父类的相关属性

2 handler 和 logger的关系

#!/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

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

此处表明,虽然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 不针对当前设置

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

此处虽然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级别

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

文件中结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

#!/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')

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

文件结果

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

#!/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')

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

文件结果

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

#!/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')

结果

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

文件结果

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

3 添加格式化处理

#!/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')

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

文件结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

4 handlers 和 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

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

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)

结果为

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

文件结果为

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

5 总结:

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的调用什么都不做。

6 filter过滤器

可以为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')

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

文件结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

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')

结果如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

文件如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

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')

文件如下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

消息loga,它的名字是's',因此过滤器名字设置为s,则s.s1,s.x和s都能通过,但其他的则不能通过,不设置过滤器名字,所有消息都能通过,设置为a,则和s,s.s1和s.s2无任何关系,因此其不能使用,实例对象只有一个,一旦同名,也是只有一个,线程的不安全不会影响logging,只会影响print。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值