python日志模块 logging

模块级函数

logging.getLogger([name]):返回一个logger对象,如果没有指定名字将返回root logger
logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical():设定root logger的日志级别
logging.basicConfig():用默认Formatter为日志系统建立一个StreamHandler,设置基础配置并加到root logger中

Logger

logging.getLogger([name])
返回一个logger实例,如果没有指定name,返回root logger。
每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:
LOG=logging.getLogger(”chat.gui”)
而核心模块可以这样:
LOG=logging.getLogger(”chat.kernel”)
 
Logger.setLevel(logging.WARNING):指定最低的日志级别,低于WARNING的级别将被忽略
Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter
Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler
 
 

Handlers

handler对象负责发送相关的信息到指定目的地。可以是文件、屏幕、网络、socket等
Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter():给这个handler选择一个输出格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象
 

日志打印到屏幕

import logging

logging.debug('This is debug message')
logging.info('This is info message')
logging.warning('This is warning message')

 

返回:
WARNING:root:This is warning message
打印到屏幕

 


默认情况下,logging将日志打印到屏幕,日志级别为WARNING;
日志级别大小关系为:CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET,当然也可以自己定义日志级别。
 

格式化日志输出

logging.basicConfig函数各参数:
filename: 指定日志文件名
filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a'
format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:

 

import logging

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='myapp.log',
                filemode='w')
    
logging.debug('This is debug message')
logging.info('This is info message')
logging.warning('This is warning message')

 

./myapp.log文件中内容为:
Sun, 24 May 2009 21:48:54 demo2.py[line:11] DEBUG This is debug message
Sun, 24 May 2009 21:48:54 demo2.py[line:12] INFO This is info message
Sun, 24 May 2009 21:48:54 demo2.py[line:13] WARNING This is warning message
修改输出格式

 

 

日志格式变量

 %(levelno)s: 打印日志级别的数值
 %(levelname)s: 打印日志级别名称
 %(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
 %(filename)s: 打印当前执行程序名
 %(funcName)s: 打印日志的当前函数
 %(lineno)d: 打印日志的当前行号
 %(asctime)s: 打印日志的时间
 %(thread)d: 打印线程ID
 %(threadName)s: 打印线程名称
 %(process)d: 打印进程ID
 %(message)s: 打印日志信息
datefmt: 指定时间格式,同time.strftime()
level: 设置日志级别,默认为logging.WARNING
stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略
日志格式

logging方法

logging.StreamHandler: 日志输出到流,可以是sys.stderr、sys.stdout或者文件
logging.FileHandler: 日志输出到文件

日志回滚方式,实际使用时用RotatingFileHandler和TimedRotatingFileHandler
logging.handlers.BaseRotatingHandler
logging.handlers.RotatingFileHandler
logging.handlers.TimedRotatingFileHandler

logging.handlers.SocketHandler: 远程输出日志到TCP/IP sockets
logging.handlers.DatagramHandler:  远程输出日志到UDP sockets
logging.handlers.SMTPHandler:  远程输出日志到邮件地址
logging.handlers.SysLogHandler: 日志输出到syslog
logging.handlers.NTEventLogHandler: 远程输出日志到Windows NT/2000/XP的事件日志
logging.handlers.MemoryHandler: 日志输出到内存中的制定buffer
logging.handlers.HTTPHandler: 通过"GET""POST"远程输出到HTTP服务器
logging方法
由于StreamHandler和FileHandler是常用的日志处理方式,所以直接包含在logging模块中,而其他方式则包含在logging.handlers模块中
 
 

在程序中定义日志模块

import logging
# create logger
def logger(log_type):
logger = logging.getLogger(log_type) # 创建Logger对象,类型是'TEST-LOG'
logger.setLevel(logging.WARNING) # 设置最低的日志级别,此级别覆盖ch and fh的级别
# 创建输出到控制台处理程序,并设置级别为DEBUG
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG) # 控制输出到屏幕的级别
# 创建输出到文件的处理程序,并设置级别
fh = logging.FileHandler("access.log")
fh.setLevel(logging.WARNING)
# 创建日志格式
formatter_Stream = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
formatter_File = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to ch and fh
ch.setFormatter(formatter_Stream)
fh.setFormatter(formatter_File)
# add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh)
return logger
eee = logger('EEE')
rrr = logger('RRR')
rrr.debug('debug message')
rrr.info('info message')
rrr.warning('warn message')
eee.error('error message')
eee.critical('critical message')
代码

 

 
屏幕显示内容
RRR - DEBUG - debug message
RRR - INFO - info message
RRR - WARNING - warn message
EEE - ERROR - error message
EEE - CRITICAL - critical message
屏幕显示内容
 
 
文件中内容
2017-02-21 21:35:05,700 - RRR - WARNING - warn message
2017-02-21 21:35:05,700 - EEE - ERROR - error message
2017-02-21 21:35:05,700 - EEE - CRITICAL - critical message
文件中内容

 

 
 

过滤器

  • 调用logging.getLogger()时参数的格式类似于“A.B.C”。采取这样的格式就是为了配置过滤器。添加过滤器后日志会经过过滤器处理后才输出
  • 过滤器"AAA.BBB"只让名字以"AAA.BBB"开头的logger输出信息
  • 可以添加多个过滤器,只要有一个过滤器拒绝,日志就不会输出
import logging
def logger(log_type):
logger = logging.getLogger(log_type) # 创建Logger对象,类型是'TEST-LOG'
logger.setLevel(logging.DEBUG) # 此级别覆盖ch and fh的级别
# 创建输出到控制台处理程序,并设置级别为DEBUG
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG) # 控制输出到屏幕的级别
 
# 设置过滤器
filter = logging.Filter('AAA.BBB.CCC')
ch.addFilter(filter)
formatter_Stream = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter_Stream)
logger.addHandler(ch) # ch加入logger
return logger
eee = logger('AAA.BBB.CCC')
rrr = logger('AAA.BBB.DDD')
rrr.error('debug message')
rrr.error('info message')
eee.error('critical message')
eee.error('critical message')
代码

 

 
 

切割日志

按大小切割
import logging
from logging import handlers
# create logger
def logger(log_type):
logger = logging.getLogger(log_type)
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler("access.log")
fh.setLevel(logging.WARNING)
# 最多备份5个日志文件,每个日志文件最大10M
fh = handlers.RotatingFileHandler(filename='access.log', maxBytes=10*1024*1024,backupCount=5)
formatter_File = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter_File)
logger.addHandler(fh)
return logger
rrr = logger('AAA.BBB.DDD')
rrr.error('debug message')
rrr.error('info message')
代码
maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。
backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。
 
 
按时间切割
import logging
from logging import handlers
# create logger
def logger(log_type):
logger = logging.getLogger(log_type)
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler("access.log")
fh.setLevel(logging.WARNING)
# 按时间切割日志文件
fh = handlers.TimedRotatingFileHandler(filename='access.log', when='s', interval=10 )
formatter_File = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter_File)
logger.addHandler(fh)
return logger
rrr = logger('AAA.BBB.DDD')
rrr.error('debug message')
rrr.error('info message')
rrr.error('warn message')
代码
interval:时间间隔
when: 时间单位 S 秒 M 分 H 小时 D 天 W 每星期(interval==0时代表星期一) midnight 每天凌晨
 
 

关于root logger以及logger的父子关系


前面多次提到root logger, 实际上logger实例之间还有父子关系, root logger就是处于最顶层的logger, 它是所有logger的祖先。如下图:root logger是默认的logger如果不创建logger实例, 直接调用logging.debug()、logging.info()logging.warning()、logging.error()、logging.critical()这些函数,那么使用的logger就是 root logger, 它可以自动创建,也是单实例的。

 


如何得到root logger通过logging.getLogger()或者logging.getLogger("")得到root logger实例。
默认的levelroot logger默认的level是logging.WARNING
如何表示父子关系logger的name的命名方式可以表示logger之间的父子关系. 比如:parent_logger = logging.getLogger('foo')child_logger = logging.getLogger('foo.bar')
什么是effective levellogger有一个概念,叫effective level。 如果一个logger没有显示地设置level,那么它就用父亲的level。如果父亲也没有显示地设置level, 就用父亲的父亲的level,以此推....最后到达root logger,一定设置过level。默认为logging.WARNINGchild loggers得到消息后,既把消息分发给它的handler处理,也会传递给所有祖先logger处理
 
本文参考地址:http://kenby.iteye.com/blog/1162698
 
 
posted @ 2017-02-21 23:25  跟随心走  阅读(331)  评论(0编辑  收藏  举报