一、logging模块介绍
logging是Python中自带的标准模块,是Python中用来操作日志的模块。
1、控制台输出日志
1 import logging 2 logging.basicConfig(level=logging.ERROR, # 打印的日志级别 3 format= 4 '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s' 5 # 日志格式 6 ) 7 logging.debug('debug级别,最低级别,一般开发人员用来打印一些调试信息') 8 logging.info('info级别,正常输出信息,一般用来打印一些正常的操作') 9 logging.warning('waring级别,一般用来打印警信息') 10 logging.error('error级别,一般用来打印一些错误信息') 11 logging.critical('critical级别,一般用来打印一些致命的错误信息')
日志级别 debug < info < warning < error < critical
设置了日志级别之后,会打印该级别以及比该级别高的所有日志,举个例子,如果日志级别是warning,那么就会打印warning、error、critical,这三个级别的日志,不会打印debug和info级别的,如果是debug,最低级别的日志,那么所有的日志都会打印。
上面的只是在控制台打印日志,并没有把日志写在文件里面,一般我们都会把日志写在日志文件里面,也很简单,只需要加个参数指定文件名就行了。
2、把日志存入日志文件
要把日志存入日志文件,需要加上filename参数(即日志文件名)以及filemode参数(写日志模式w为覆盖,a为追加),没有加filename参数时,控制台会输出日志信息,加了filename参数后,控制台不会再输出日志信息。
1 import logging 2 # 没有加filename参数时,控制台有输出日志信息,加了filename参数时,控制台不会再输出日志信息 3 logging.basicConfig(level=logging.ERROR, # 打印的日志级别 4 filename='my.log', # 日志文件名 5 filemode='a', # w清空,a追加写入,不会清空 6 format= 7 '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s' 8 # 日志格式 9 ) 10 logging.debug('debug级别,最低级别,一般开发人员用来打印一些调试信息') 11 logging.info('info级别,正常输出信息,一般用来打印一些正常的操作') 12 logging.warning('waring级别,一般用来打印警信息') 13 logging.error('error级别,一般用来打印一些错误信息') 14 logging.critical('critical级别,一般用来打印一些致命的错误信息')
运行后发现能够生成日志文件,但日志文件里面的中文显示为乱码,且控制台不再打印日志信息。
1 # 可以指定日志的输出格式format,这个参数可以输出很多有用的信息,如下面的几种格式: 2 # % (levelno)s: # 打印日志级别的数值 3 # % (levelname)s: # 打印日志级别名称 4 # % (pathname)s: # 打印当前执行程序的路径,其实就是sys.argv[0] 5 # % (filename)s: # 打印当前执行程序名 6 # % (funcName)s: # 打印日志的当前函数 7 # % (lineno)d: # 打印日志的当前行号 8 # % (asctime)s: # 打印日志的时间 9 # % (thread)d: # 打印线程ID 10 # % (threadName)s: # 打印线程名称 11 # % (process)d: # 打印进程ID 12 # % (message)s: # 打印日志信息 13 # 常用格式: 14 # format = '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s' 15 # 这个格式可以输出日志的打印时间,是哪个文件第几行输出的,输出的日志级别是什么,以及输入的日志内容。
3、同时实现控制台输出日志、写入日志文件
logging模块中主要有4个类,分别负责不同的工作:
(1)Logger记录器:暴露了应用程序代码能直接使用的接口。简单点说就是一个创建一个办公室,让人在里头工作
(2)Handler 处理器:将(记录器产生的)日志记录发送至合适的目的地。这个简单点说就是办事的人,你可以指定是让在控制输出日志,还是在文件里面打 印日志,常用的有4种:
后面两种需要导入handlers,from logging import handlers
a、StreamHandler 控制台输出
b、FileHandler 文件输出
c、TimedRotatingFileHandler 按照时间自动分割日志文件
d、RotatingFileHandler 按照大小自动分割日志文件,一旦达到指定的大小重新生成文件
(3)Filter过滤器:提供了更好的粒度控制,它可以决定输出哪些日志记录。(不常用)
(4)Formatter格式化器:指明了最终输出中日志记录的布局。指定输出日志的格式
具体怎么实现呢?得有个办公室,里面放两个人,一个负责往控制台输出日志,一个负责将日志写入日志文件。
1 import logging 2 from logging import handlers 3 logger = logging.getLogger() # 先实例化一个logger对象,先创建一个办公室 4 logger.setLevel(logging.DEBUG) # 设置日志的总级别 5 # 创建一个文件处理器,也就是把日志写到文件里(fh的功能包含在th当中,所以fh可以删除不写) 6 fh = logging.FileHandler(filename='my.log',mode='a',encoding='utf-8') 7 fh.setLevel(logging.ERROR) # 设定文件输出的日志级别 8 # 创建一个控制台输出的处理器 9 sh = logging.StreamHandler() 10 sh.setLevel(logging.INFO) # 设置控制台输出的日志级别 11 # 创建一个指定间隔时间自动生成日志文件的处理器,这个相对于fh更好用 12 th = handlers.TimedRotatingFileHandler(filename='a.log',when='S',interval=1,backupCount=3,encoding='utf-8') 13 # interval是时间间隔,backupCount是备份文件的个数,如果超过这个超过这个个数,就会自动删除 14 # when是间隔的时间单位,单位有以下几种: 15 # S 秒 16 # M 分 17 # H 小时 18 # D 天 19 # W 星期(interval==0时代表星期一) 20 # midnight 每天凌晨 21 th.setLevel(logging.INFO) # 设定自动生成日志文件的日志级别 22 # 以上三个日志级别都可以单独设置,他们和总日志级别logger的级别区别是如果logger设置的级别比里面的handler级别设置的高,那么就以logger的级别为准 23 # 指定日志格式 24 formater = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s') 25 fh.setFormatter(formater) # 设置文件处理器输出的日志格式 26 sh.setFormatter(formater) # 设置控制台输出的日志格式 27 th.setFormatter(formater) # 设置文件里面写入的日志格式 28 # 把三个handler加入容器里头,相当于把工作人员培训完了,你们可以上班了 29 logger.addHandler(fh) # 把文件处理器放到办公室 30 logger.addHandler(sh) # 把控制台输出的处理器放到办公室 31 logger.addHandler(th) # 把第二个文件处理器放到办公室 32 33 # 执行 34 logger.debug('debug级别,最低级别,一般开发人员用来打印一些调试信息') 35 logger.info('info级别,正常输出信息,一般用来打印一些正常的操作') 36 logger.warning('waring级别,一般用来打印警信息') 37 logger.error('error级别,一般用来打印一些错误信息') 38 logger.critical('critical级别,一般用来打印一些致命的错误信息')
二、封装写日志的类
1 # 封装写日志的类 2 import logging 3 from logging import handlers 4 class MyLogger(): 5 def __init__(self,file_name,level='info',backCount=5,when='D'): 6 logger = logging.getLogger() # 先实例化一个logger对象,先创建一个办公室 7 logger.setLevel(self.get_level(level)) # 设置日志级别 8 ch = logging.StreamHandler() # 负责往控制台输出日志 9 bh = handlers.TimedRotatingFileHandler(filename=file_name,when=when,interval=1,backupCount=backCount,encoding='utf-8') 10 formater = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s') 11 ch.setFormatter(formater) # 设置控制台输出的日志格式 12 bh.setFormatter(formater) # 设置文件里面写入的日志格式 13 logger.addHandler(ch) # 把把用于控制台输出的实例放入logger 14 logger.addHandler(bh) # 把用于写文件的实例放入logger 15 self.logger = logger 16 def get_level(self,str): # 该函数把输入的字符串转换成日志级别(debug转换成logging.DEBUG) 17 level = { 18 'debug':logging.DEBUG, 19 'info':logging.INFO, 20 'waring':logging.WARNING, 21 'error':logging.ERROR, 22 'critical':logging.CRITICAL 23 } 24 str = str.lower() 25 return level.get(str) 26 27 mylog = MyLogger('my.log','debug') 28 mylog.logger.warning('waring级别日志')
三、第三方模块nnlog
直接pip install nnlog即可,使用例子如下面代码:
1 import nnlog 2 # 实例化 3 log = nnlog.Logger(file_name='my.log', level='debug', when='D', backCount=5, interval=1) 4 # file_name是日志文件名 5 # level是日志级别,如果不传的话默认是debug级别 6 # when是日志文件多久生成一个,默认是按天,S 秒、M 分、 H 小时、 D 天、 W 每星期 7 # backCount是备份几个日志文件,默认保留5天的 8 # interval是间隔多久生成一个日志文件,默认是1天 9 log.debug('默认日志级别是debug') 10 log.info('info级别') 11 log.warning('waring级别') 12 log.error('error级别')