设为首页 收藏本站
查看: 1289|回复: 0

[经验分享] python的logging模块详解

[复制链接]

尚未签到

发表于 2018-8-9 11:31:10 | 显示全部楼层 |阅读模式
  日志级别
>>>import logging  
>>>logging.NOTSET
  
0
  
>>>logging.DEBUG
  
10
  
>>>logging.INFO
  
20
  
>>>logging.WARN
  
30
  
>>>logging.ERROR
  
40
  
>>>logging.CRITICAL
  
50
  
>>>logging._levelNames
  
{0:'NOTSET', 10: 'DEBUG', 'WARN': 30, 20: 'INFO', 'ERROR': 40, 'DEBUG': 10, 30:'WARNING', 'INFO': 20, 'WARNING': 30, 40: 'ERROR', 50: 'CRITICAL', 'CRITICAL':50, 'NOTSET': 0}
  从以上可以看出logging模块输出日志默认共有6个级别,级别大小依次是CRITICAL>ERROR> WARN> INFO> DEBUG> NOTSET
  日志默认输出级别
[root@ju tmp]# cat log.py  
#!/usr/bin/envpython
  
importlogging
  
logging.debug('Thisis debug level')
  
logging.info('Thisis info level')
  
logging.warning('Thisis warning level')
  
logging.error('Thisis error level')
  
logging.critical('Thisis critical level')
  输出结果如下:
[root@ju tmp]# python log.py  
WARNING:root:Thisis warning level
  
ERROR:root:Thisis error level
  
CRITICAL:root:Thisis critical level
  从执行结果可以看出,logging模块的日志输出级别默认是warning级别。
  自定义日志格式并输出到文件
  日志的输出格式和方式可以通过logging.basicConfig函数配置。
#!/usr/bin/envpython  
#coding=utf-8
  
importlogging
  
logging.basicConfig(level=logging.DEBUG,
  
    format='%(asctime)s%(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
  
    datefmt='%a, %d %b %Y %H:%M:%S',
  
    filename='test.log',
  
    filemode='a')
  
'''
  
可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
  
filename:          指定日志文件名
  
filemode:          指定日志文件的打开模式,'w'覆盖或'a'追加
  
format:            定义输出的格式和内容
  
datefmt:           指定时间格式,同time.strftime()
  
level:            设置rootlogger的日志级别
  
stream:            用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
  
'''
  
logging.debug('Thisis debug level')
  
logging.info('Thisis info level')
  
logging.warning('Thisis warning level')
  
logging.error('Thisis error level')
  
logging.critical('Thisis critical level')
[root@ju python_moudle]# python logtest.py  

  
输出结果如下:
  
[root@ju python_moudle]# cat test.log
  
Mon, 15Jun 2015 03:48:01 logtest.py[line:10] DEBUG This is debug level
  
Mon, 15Jun 2015 03:48:01 logtest.py[line:11] INFO This is info level
  
Mon, 15Jun 2015 03:48:01 logtest.py[line:12] WARNING This is warning level
  
Mon, 15Jun 2015 03:48:01 logtest.py[line:13] ERROR This is error level
  
Mon, 15Jun 2015 03:48:01 logtest.py[line:14] CRITICAL This is critical level
  自定义日志格式并输出到控制台
[root@ju python_moudle]# cat logtest.py  
#!/usr/bin/envpython
  
#coding=utf-8
  
importlogging
  
#定义一个StreamHandler,将INFO级别或更高的日志信息打印到标准错误,并将其添加到当前的日志处理对象#
  
console= logging.StreamHandler()  #StreamHandler输出到控制台,FileHandler输出到文件.
  
console.setLevel(logging.WARN)
  
formatter= logging.Formatter('%(name)-8s: %(levelname)-12s %(message)s')
  
console.setFormatter(formatter)
  
logging.getLogger('').addHandler(console)
  

  
logging.debug('Thisis debug level')
  
logging.info('Thisis info level')
  
logging.warning('Thisis warning level')
  
logging.error('Thisis error level')
  
logging.critical('Thisis critical level')
  输出结果如下:
[root@ju python_moudle]# python logtest.py  
root    : WARNING      This is warning level
  
root    : ERROR         Thisis error level
  
root    : CRITICAL      Thisis critical level
  Handlers
  handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。StreamHandler可以把信息输出到控制台,FileHandler可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler。
  Handler.setLevel(levelname):指定被处理的信息级别,低于levelname级别的信息将被忽略
  Handler.setFormatter():给这个handler指定一个格式
  Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象
  Logging模块中有多中可用的Handler:
  logging.StreamHandler                 可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息
  logging.FileHandler                用于向一个文件输出日志信息
  logging.handlers.RotatingFileHandler  类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建一个新的同名日志文件继续输出
  logging.handlers.TimedRotatingFileHandler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就自动创建新的日志文件
  logging.handlers.SocketHandler      使用TCP协议,将日志信息发送到网络。
  logging.handlers.DatagramHandler    使用UDP协议,将日志信息发送到网络。
  logging.handlers.SysLogHandler      日志输出到syslog
  logging.handlers.NTEventLogHandler  远程输出日志到Windows NT/2000/XP的事件日志
  logging.handlers.SMTPHandler       远程输出日志到邮件地址
  logging.handlers.MemoryHandler     日志输出到内存中的制定buffer
  logging.handlers.HTTPHandler       通过"GET"或"POST"远程输出到HTTP服务器
  各个Handler的具体用法可查看参考书册:
  https://docs.python.org/2/library/logging.handlers.html#module-logging.handlers
  Formatters
  Formatter对象设置日志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d%H:%M:%S,下面是Formatter常用的一些信息。
  %(name)s                  Logger的名字
  %(levelno)s:           打印日志级别的数值
  %(levelname)s:        打印日志级别名称
  %(pathname)s:        打印当前执行程序的路径,其实就是sys.argv[0]
  %(filename)s:         打印当前执行程序名
  %(module)s               调用日志输出函数的模块名
  %(funcName)s:      打印日志的当前函数
  %(lineno)d:           打印日志的当前行号
  %(created)f                当前时间,用UNIX标准的表示时间的浮点数表示
  %(relativeCreated)d    输出日志信息时的,自Logger创建以来的毫秒数
  %(asctime)s:          打印日志的时间
  %(thread)d:           打印线程ID
  %(threadName)s:      打印线程名称
  %(process)d:          打印进程ID
  %(message)s:         打印日志信息
  getLogger模块详解
  logging.getLogger()时参数的格式类似于“arg1.arg2.arg3”,上代码:
[root@ju python_moudle]# cat logtest.py  
#!/usr/bin/envpython
  
#coding=utf-8
  
importlogging
  
#创建一个logger
  
logroot= logging.getLogger()
  

  
log1 =logging.getLogger('L1')
  
log1.setLevel(logging.DEBUG)
  

  
log2 =logging.getLogger('L1.L2')
  
log2.setLevel(logging.INFO)
  

  
log3 = logging.getLogger('L1.L2.L3')
  
log3.setLevel(logging.WARNING)
  
#创建一个handler,用于输出到控制台
  
ch =logging.StreamHandler()
  
#定义handler的输出格式formatter
  
formatter= logging.Formatter('%(name)s - %(levelname)s - %(message)s')
  
ch.setFormatter(formatter)
  
#给logger添加handler
  
logroot.addHandler(ch)
  
log1.addHandler(ch)
  
log2.addHandler(ch)
  
log3.addHandler(ch)
  
#打印日志
  
logroot.debug('logrootdebug message')
  
logroot.info('logrootinfo message')
  
logroot.warning('logrootwarning message')
  
logroot.error('logrooterror message')
  
logroot.critical('logrootcritical message')
  

  
log1.debug('log1debug message')
  
log1.info('log1info message')
  
log1.warning('log1warning message')
  
log1.error('log1error message')
  
log1.critical('log1critical message')
  

  
log2.debug('log2debug message')
  
log2.info('log2info message')
  
log2.warning('log2warning message')
  
log2.error('log2error message')
  
log2.critical('log2critical message')
  

  
log3.debug('log3debug message')
  
log3.info('log3info message')
  
log3.warning('log3warning message')
  
log3.error('log3error message')
  
log3.critical('log3critical message')
  输出结果如下:
[root@jupython_moudle]# python logtest.py  
root -WARNING - logroot warning message
  
root -ERROR - logroot error message
  
root -CRITICAL - logroot critical message
  
L1 -DEBUG - log1 debug message
  
L1 -DEBUG - log1 debug message
  
L1 -INFO - log1 info message
  
L1 -INFO - log1 info message
  
L1 -WARNING - log1 warning message
  
L1 -WARNING - log1 warning message
  
L1 -ERROR - log1 error message
  
L1 -ERROR - log1 error message
  
L1 -CRITICAL - log1 critical message
  
L1 -CRITICAL - log1 critical message
  
L1.L2 -INFO - log2 info message
  
L1.L2 -INFO - log2 info message
  
L1.L2 -INFO - log2 info message
  
L1.L2 -WARNING - log2 warning message
  
L1.L2 -WARNING - log2 warning message
  
L1.L2 -WARNING - log2 warning message
  
L1.L2 -ERROR - log2 error message
  
L1.L2 -ERROR - log2 error message
  
L1.L2 -ERROR - log2 error message
  
L1.L2 -CRITICAL - log2 critical message
  
L1.L2 -CRITICAL - log2 critical message
  
L1.L2 -CRITICAL - log2 critical message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  由以上输出结果可以看出rootlog的每个输出分别打印1次,log1对应的输出分别打印了2次,log2对应的输出打印了3次,log3打印4次。logger = logging.getLogger()显示的创建了root Logger,这是因为logger实例之间的“父子关系”,rootlogger处于最顶层,log1是第二层,log2是第三层,以此类推。所以在把消息分发给它们的handler进行处理时也会传递给所有的祖先Logger处理。
  现在把以下两行注释,再输出
logroot.addHandler(ch)  
log1.addHandler(ch)
  输出结果如下:
[root@ju python_moudle]# python logtest.py  
Nohandlers could be found for logger "root"
  
L1.L2 -INFO - log2 info message
  
L1.L2 -WARNING - log2 warning message
  
L1.L2 -ERROR - log2 error message
  
L1.L2 -CRITICAL - log2 critical message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  这时候可以看到log2就变成最顶层的节点,log3在handler时还是要传递给log2处理一遍,所以输出两遍。
  使用filter设置过滤器
  限制只有满足过滤规则的日志才会输出。比如我们定义了filter = logging.Filter('L1.L2.L3'),并将这个Filter添加到了一个Handler上,则使用该Handler的Logger中只有名字带a.b.c前缀的Logger才能输出其日志。看代码:
[root@jupython_moudle]# cat logtest.py  
#!/usr/bin/envpython
  
#coding=utf-8
  
importlogging
  

  
#创建一个logger
  
logroot= logging.getLogger()
  
log1 =logging.getLogger('L1')
  
log1.setLevel(logging.DEBUG)
  
log2 =logging.getLogger('L1.L2')
  
log2.setLevel(logging.INFO)
  
log3 =logging.getLogger('L1.L2.L3')
  
log3.setLevel(logging.WARNING)
  
#再创建一个handler,用于输出到控制台
  
ch =logging.StreamHandler()
  
#定义handler的输出格式formatter
  
formatter= logging.Formatter('%(name)s - %(levelname)s - %(message)s')
  
ch.setFormatter(formatter)
  
#定义filter
  
f =logging.Filter('L1.L2.L3')
  
ch.addFilter(f)
  
#给logger添加handler
  
logroot.addHandler(ch)
  
log1.addHandler(ch)
  
log2.addHandler(ch)
  
log3.addHandler(ch)
  
#打印日志
  
logroot.debug('logrootdebug message')
  
logroot.info('logrootinfo message')
  
logroot.warning('logrootwarning message')
  
logroot.error('logrooterror message')
  
logroot.critical('logrootcritical message')
  

  
log1.debug('log1debug message')
  
log1.info('log1info message')
  
log1.warning('log1warning message')
  
log1.error('log1error message')
  
log1.critical('log1critical message')
  

  
log2.debug('log2debug message')
  
log2.info('log2info message')
  
log2.warning('log2warning message')
  
log2.error('log2error message')
  
log2.critical('log2critical message')
  

  
log3.debug('log3debug message')
  
log3.info('log3info message')
  
log3.warning('log3warning message')
  
log3.error('log3error message')
  
log3.critical('log3critical message')
  输出结果如下:
[root@ju python_moudle]# python logtest.py  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  由输出结果可以看到,正如前面所说,只输出以L1.L2.L3开头的logger了。但是为Handler加Filter后只要使用了该Handler的Logger都会受影响。而为Logger单独添加Filter只会影响到自身。看代码:
#定义filter  
f =logging.Filter('L1.L2')
  
#ch.addFilter(f)                   #把此行注释
  
#给logger添加filter和handler
  
logroot.addHandler(ch)
  
log1.addFilter(f)                  #给log1加上filter
  
log1.addHandler(ch)
  
log2.addFilter(f)                  #给log2加上filter
  
log2.addHandler(ch)
  
log3.addHandler(ch)
  输出结果如下:
[root@ju python_moudle]# python logtest.py  
root -WARNING - logroot warning message
  
root -ERROR - logroot error message
  
root -CRITICAL - logroot critical message
  
L1.L2 -INFO - log2 info message
  
L1.L2 -INFO - log2 info message
  
L1.L2 -INFO - log2 info message
  
L1.L2 -WARNING - log2 warning message
  
L1.L2 -WARNING - log2 warning message
  
L1.L2 -WARNING - log2 warning message
  
L1.L2 -ERROR - log2 error message
  
L1.L2 -ERROR - log2 error message
  
L1.L2 -ERROR - log2 error message
  
L1.L2 -CRITICAL - log2 critical message
  
L1.L2 -CRITICAL - log2 critical message
  
L1.L2 -CRITICAL - log2 critical message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- WARNING - log3 warning message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- ERROR - log3 error message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  
L1.L2.L3- CRITICAL - log3 critical message
  由以上输出可以看到rootlog并未受影响,log1由于未匹配到所以没有输出,log2匹配到说以输出,log3未定义filter也可能输出。
  通过logging.config模块配置日志
[root@jupython_moudle]# cat log.conf  
[loggers]
  
keys=root,TestLogger
  

  
[handlers]
  
keys=consoleHandler
  

  
[formatters]
  
keys=TestFormatter
  

  
[logger_root]
  
level=DEBUG
  
handlers=consoleHandler
  

  
[logger_TestLogger]
  
level=DEBUG
  
handlers=consoleHandler
  
qualname=TestLogger
  
propagate=0
  

  
[handler_consoleHandler]
  
class=StreamHandler
  
level=DEBUG
  
formatter=TestFormatter
  
args=(sys.stdout,)
  

  
[formatter_TestFormatter]
  
format=%(asctime)-12s%(name)-12s %(levelname)-12s %(message)s
  
datefmt='%a,%d %b %Y %H:%M:%S'
[root@jupython_moudle]# cat logtest.py  
#!/usr/bin/envpython
  
#coding=utf-8
  
importlogging
  
importlogging.config
  

  
logging.config.fileConfig('log.conf')  #使用log.conf配置文件
  

  
#创建日志
  
LOG =logging.getLogger("TestLogger")
  

  
LOG.debug('Thisis debug level')
  
LOG.info('Thisis info level')
  
LOG.warning('Thisis warning level')
  
LOG.error('Thisis error level')
  
LOG.critical('Thisis critical level')
  结果输出如下:
[root@ju python_moudle]# python logtest.py  
'Mon, 15Jun 2015 08:04:49' TestLogger  DEBUG        This is debug level
  
'Mon, 15Jun 2015 08:04:49' TestLogger   INFO         This is info level
  
'Mon, 15Jun 2015 08:04:49' TestLogger  WARNING      This is warning level
  
'Mon, 15Jun 2015 08:04:49' TestLogger  ERROR        This is error level
  
'Mon, 15Jun 2015 08:04:49' TestLogger  CRITICAL     This is criticallevel

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-549108-1-1.html 上篇帖子: Python re-90SirDB 下篇帖子: python中if __name__ == "__main__"的解释
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表