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' | 每天的凌晨