1、最简单的例子
#coding=utf-8
import logging
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
执行这段代码,可以得到如下结果
WARNING:root:warning
ERROR:root:error
CRITICAL:root:critical
debug,和info 并没有输出,这是因为logging默认的日志级别是warning,只有大于等于这个级别的日志才会被输出,日志级别的顺序是这样的:
CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET
2、输出的到文件中
第一节中的例子,只是在终端输出了日志,显然,工程实践里,我们需要把日志写到文件中,这样才能供日后审查使用
#coding=utf-8
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='test_log.log',
filemode='w')
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
在这个例子中,basicConfig设置了基础参数
level 设置日志级别
format 设置日志格式
datefmt 设置日期格式
filename 设置目标文件
filemode 设置文件打开模式,例子中是w,每次重新启动程序,日志都会重头写,之前的内容被覆盖掉,如果想追加写,可设置成a+
format 可用到很多参数:
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s 用户输出的消息
3、更灵活的控制
3.1 getlogger
#coding=utf-8
import logging
logger = logging.getLogger('kwsy')
formatter = logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s',datefmt='%a, %d %b %Y %H:%M:%S')
fh = logging.FileHandler('test_log.log')
fh.setFormatter(formatter)
logger.addHandler(fh)
logger.setLevel(logging.INFO)
logger.info('info')
getlogger返回一个logger对象,注意里面的参数,它非常有用,输出结果是
Thu, 06 Jul 2017 09:16:47 - kwsy - INFO - info
为日志设置一个名字是很有必要的,它可以帮你日志的来源是哪里
3.2 不同级别的日志
有必要将不同级别的日志写入到不同文件中,这样便于分析,但你不必创建多个looger对象,只需要一个就可以了
#coding=utf-8
import logging
logger = logging.getLogger('kwsy')
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s',datefmt='%a, %d %b %Y %H:%M:%S')
class LogLevelFilter(logging.Filter):
def __init__(self, name='', level=logging.INFO):
super(LogLevelFilter,self).__init__(name)
self.level = level
def filter(self, record):
return record.levelno <= self.level
info_handler = logging.FileHandler('info.log')
info_handler.setFormatter(formatter)
info_handler.setLevel(logging.DEBUG)
info_handler.addFilter(LogLevelFilter())
logger.addHandler(info_handler)
err_handler = logging.FileHandler('err.log')
err_handler.setFormatter(formatter)
err_handler.setLevel(logging.WARNING)
logger.addHandler(err_handler)
logger.debug('debug')
logger.info('info')
logger.warning('warning')
logger.error('err')
上面的例子中,只有一个logger对象,但是有两个FileHandler对象,先来看err_handler对象,它的日志级别是warning,大于等于这个级别的日志都会被写入到err.log中;再来看info_handler对象,它的日志级别是debug,按道理,warning和error日志也会被写入到info.log中,因为他们的级别都比debug大,但是,info_handler加了一个filter,这个filter将大于info级别的日志都过滤掉了,只记录debug和info日志
3.3 WatchedFileHandler
#coding=utf-8
import logging
import time
from logging.handlers import WatchedFileHandler
logger = logging.getLogger('kwsy')
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s',datefmt='%a, %d %b %Y %H:%M:%S')
info_handler = WatchedFileHandler('info.log')
#info_handler = logging.FileHandler('info.log')
info_handler.setFormatter(formatter)
info_handler.setLevel(logging.DEBUG)
logger.addHandler(info_handler)
while True:
logger.info('info')
time.sleep(3)
上面这段代码和之前的例子相差不多,区别在于使用了 WatchedFileHandler,它和Filehandler有什么不同呢?
执行这段代码,会生成一份info.log文件,这时,执行命令 mv info.log info.log.bak ,将文件重命名,程序会关闭之前的文件流,重新生成一份info.log文件,但如果你使用FileHandler就不会有这样的效果,WatchedFileHandler 会观察文件的状态,如果文件发生了变化,它会重新生成日志文件,这样,你的日志信息就不会丢失了。
3.4 RotatingFileHandler
class logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0)
循环日志,可以设置 maxBytes当文件的大小超过这个数值时,会创建一个新的日志文件,backupcount 是备份数目,这两个参数如果有一个为0,那么就不会触发循环写
3.5 TimedRotatingFileHandler
class logging.handlers.TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False)
定时生成新日志文件,例如 when=‘D’,interval=2 就表示每隔两天就生成一份新的文件,when 可取的参数如下
'S' | 秒
'M' | 分
'H' | 时
'D' | 天
'W0'-'W6' | 周一至周日
'midnight' | 每天的凌晨