python logging模块练习
使用logging提供的模块级别的函数记录日志:
实例1:日志保存到文件
import logging
#日志配置中加入filename配置 logging.basicConfig(filename='test.log', filemode='a', format='%(asctime)s - %(levelname)s - %(name)s - %(message)s', datefmt='%Y-%m-%d',level=logging.WARNING) # 输出日志 logging.info('this is info') logging.debug('this is debug') logging.warning('this is warning') logging.error('this is error') logging.critical('this is critical')
注意:
- 这里参数filename、stream、handlers不能同时配置,否者报错ValueError异常。
- 参数format的传入只能为字符串,不能为logging.Formatter()对象。
实例2:日志添加handlers
import logging
# 创建handlers h_1=logging.StreamHandler() h_1.setLevel(logging.WARNING) h_1.setFormatter(logging.Formatter('%(asctime)s - %(name)s - \'h_1\' - %(levelname)s - %(message)s')) # 日志配置 logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d', level=logging.DEBUG,handlers=[h_1]) # 输出日志 logging.info('this is info') logging.debug('this is debug') logging.warning('this is warning') logging.error('this is error') logging.critical('this is critical')
注意:
-
logging.basicConfig() 的参数handlers必须是个可迭代对象,如果直接传入h_1会报错。
实例3:logging.basicConfig()一次性配置问题
代码:
import logging
log_format='%(asctime)s - %(name)s - %(levelname)s : %(message)s' logging.basicConfig(filename=r'C:\Users\EDZ\Desktop\log.txt',filemode='a+',level=logging.DEBUG,datefmt='%Y-%m-%d',format=log_format) logging.warning('this is a warining change 1 ') logging.basicConfig(filename=r'C:\Users\EDZ\Desktop\log.txt',filemode='a+',level=logging.ERROR,datefmt='%Y-%m-%d %H:%M:%S',format=log_format) logging.warning('this is a warining change 2')
输出:
2019-07-17 - root - WARNING : this is a warining change 1 2019-07-17 - root - WARNING : this is a warining change 2
注意:
- 只有在第一次调用该函数时会起作用,后续再次调用该函数时完全不会产生任何操作的,多次调用的设置并不是累加操作。
使用自定义Logger类和logging提供的四组件处理日志:
基本思路:
- 创建一个Logger对象,Logger对象可以(需要)配置evel、handlers组件、filter组件。
- handlers组件可以配置(需要)level、formatters组件、filter组件。
- 将handlers组件和formatters组件、filter组件拼接,将Logger与handlers组件、filter组件拼接。
基本流程:
- 用logger=logging.getLogger(‘name’)创建一个日志记录器实例logger,logger.setLevel()设置logger的日志等级。
- 创建一个handler=logging.StreamHandler(),这里以流输出handler为例,handler.setLevel()设置handler等级,handler.Formatter()设置handler的组件formatters,handler.addFilter()和handler.removeFilter()增加和删除filter组件,handler组件配置完成。
- 用logger.addHandler() 和 logger.removeHandler()为logger添加和删除handler组件,logger.addFilter()和logger.removeFilter()为logger添加和删除filter组件,logger配置完成。
- 用logger.info()等输入日志。
实操代码:
import logging import logging.handlers import datetime # 创建一个日志记录器logger logger = logging.getLogger('logger') # 设置记录器日志等级、格式 logger.setLevel(logging.INFO) # 创建handler1,在控制台输出日志,日志等级为info,设置信息日期格式 handler1 = logging.StreamHandler() handler1.setLevel(logging.INFO) handler1_fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S') # 设置日期格式为2019-07-08 handler1.setFormatter(handler1_fmt) # 设置日志信息格式 logger.addHandler(handler1) # 创建handler2,在文件中输出日志,日志等级为warining handler2 = logging.FileHandler(filename=r'C:\Users\EDZ\Desktop\warning.log', mode='w', encoding='utf-8') # mode设置文件为只写模式,如果输出中文要编码为utf-8不然会乱码 handler2.setLevel(logging.WARNING) handler2_fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S') # 设置日期格式为2019-07-08 12:00:00 handler2.setFormatter(handler2_fmt) logger.addHandler(handler2) # 创建handler3,文件中输出日志,按照文件大小1024byte将日志拆分为多个的日志文件,日志等级为error # 在使用logging.handlers模块的时候要import logging.handlers,因为import logging不会自动导入这个子模块 handler3 = logging.handlers.RotatingFileHandler(filename=r'C:\Users\EDZ\Desktop\err.log', mode='a', maxBytes=1024, encoding='utf-8') handler3.setFormatter(handler2_fmt) logger.addHandler(handler3) # 创建handler4,文件中输出日志,按照时间每天早上7点将日志拆分为多个的日志文件,日志等级为error handler4 = logging.handlers.TimedRotatingFileHandler(filename=r'C:\Users\EDZ\Desktop\err.log', when='midnight', interval=1, encoding='utf-8', atTime=datetime.time(7, 0, 0, 0)) ''' 参数when表示时间间隔类型,'S':Seconds,'M':Minutes,'H':Hours,'D':Days,'W0'-'W6':Weekday (0=Monday),'midnight':Roll over at midnight 参数atTime,设置文件拆分的时间点,数据类型为datetime类 ''' handler4.setFormatter(handler2_fmt) logger.addHandler(handler4) # 创建handler5,将日志用邮件发送到指定邮箱,日志等级为error handler5=logging.handlers.SMTPHandler(mailhost=(smtp服务器,服务器端口), fromaddr='发件人', toaddrs='收件人1,收件人2,...,收件人N', subject='邮件标题', credentials=('账号', '密码') ) #fromaddr与credentials的账号要一致 handler5.setLevel(logging.ERROR) handler5.setFormatter(handler2_fmt) logger.addHandler(handler5) logger.info('this is a info') logger.warning('this is a warning') logger.error('this is a error') logger.critical('this is a critical')
临时禁用日志方法
说明:
有些时候我们要临时禁止日志输出,或者当达到某个条件的时候再让日志开始输出,就可以用临时禁用日志的方式来达到。
方法:
- 如果是默认配置下,可以通过logging.disable(level)设置临时禁止日志等级的方式。
- 如果自定义Logger类,可以通过Logger类的属性logger.disabled=True来设置。
实操代码:
import logging # 默认配置下 logging.disable(logging.CRITICAL) #设置所有日志等级临时禁用 logging.critical('this is a critical') logging.disable(logging.WARNING) #设置日志等级小于等于warning的日志临时禁用 logging.warning('this is a warning') logging.critical('this is an critical') logging.disable(logging.NOTSET) #解除禁用,注意由于默认配置下的日志等级为warning所以这里的info不会输出 logging.info('this is an info') logging.error('this is an error') logging.basicConfig(level=logging.INFO) #修改默认配置后输出,但依旧不输出info,因为默认配置必须在logging.disable()之前设置,即将此行移动到第一行即可输出info logging.disable(logging.NOTSET) logging.info('this is an info') logging.error('this is an error')
# 自定义Logger类 logger=logging.getLogger() logger.setLevel(logging.NOTSET) logger.disabled=True # 当i=8的时候解除临时禁用 for i in range(10): logger.info('this is an info') if i == 8 : logger.disabled = False
实战的坑
一、自定义Logger之后不要和默认配置的logging同时使用,否则会重复输出日志。