logging模块
简单配置法
import logging logging.debug('debug message') # 调试 logging.info('info message') # 普通信息 logging.warning('warning message') # 警告 logging.error('error message') # 错误信息 logging.critical('critical message') # 严重错误
简单配置
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='/tmp/test.log', filemode='w') logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message')
简单配置方法容易出现的问题:默认情况下是不打印WARNING以下级别的信息(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG)
1.中文显示乱码
2.不能同时输出到文件和屏幕
logger对象法
import logging logger = logging.getLogger() # 创建一个handler,用于写入日志文件 fh = logging.FileHandler('test.log',encoding='utf-8') # 再创建一个handler,用于输出到控制台 ch = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setLevel(logging.DEBUG) fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) #logger对象可以添加多个fh和ch对象 logger.addHandler(ch) logger.debug('logger debug message') logger.info('logger info message') logger.warning('logger warning message') logger.error('logger error message') logger.critical('logger critical message')
logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然,也可以通过fh.setLevel(logging.Debug)单对文件流设置某个级别。
# 备注说明
import logging # 用logger # 首先 先创建logger对象 logger = logging.getLogger() logger.setLevel(logging.DEBUG) # 第二 创建一个文件操作符 fh = logging.FileHandler('log',encoding='utf-8') # 第三 创建一个屏幕操作符 sh = logging.StreamHandler() # 第四 创建一个格式 fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # logger 绑定 文件操作符 logger.addHandler(fh) # logger 绑定 屏幕操作符 logger.addHandler(sh) # 文件操作符 绑定格式 fh.setFormatter(fmt) # 屏幕操作符 绑定格式 sh.setFormatter(fmt) logger.debug('logger debug message') logger.info('logger info message') logger.warning('logger warning message') logger.error('logger error message') logger.critical('logger critical message')
logging模块易错问题
import logging class Log(object): def __init__(self,level = logging.DEBUG): logger = logging.getLogger() # getLogger每次都返回同一个对象 # 实现了一个单例模式 logger.setLevel(level) fh = logging.FileHandler('test.log', encoding='utf-8') ch = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setLevel(logging.DEBUG) fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) logger.addHandler(ch) self.logger = logger log = Log() log.logger.info('wahaha01') log = Log() log.logger.info('wahaha02') log = Log() log.logger.info('wahaha03')
结果显示:
是有问题的,问题原因是由于getLogger点进去查看,每次都次都返回的是同一个对象root,这样就相当于一个单例模式
如何改进:(同样也使用单例模式)
class Log(object): __instance = None def __new__(cls, *args, **kwargs): if not cls.__instance: cls.__instance = super().__new__(cls) return cls.__instance def __init__(self,level = logging.DEBUG): if 'logger' not in self.__dict__: logger = logging.getLogger() logger.setLevel(level) fh = logging.FileHandler('test.log', encoding='utf-8') ch = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setLevel(logging.DEBUG) fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) logger.addHandler(ch) self.logger = logger log = Log() log = Log() log = Log() log = Log() log.logger.info('wahaha')
结果显示:
上面代码中使用单例模式,同时也在__init__中判断之前是否存在logger这个属性,如果不存在(not in )则执行后面的代码。