为了实现在不同的环境记录不同详细程度的日志,这就需要用到日志等级了。
logging模块是Python的一个标准库模块,logging模块定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统。
(1)在error_test1.py中写入代码
import logging
logging.debug('this is a debug message')
logging.info('this is a info message')
logging.warning('this is a warning message')
logging.error('this is a error message')
logging.critical('this is a critical message')
(2)控制台输出
可以看到,在默认情况下python的logging模块会将日志打印在控制台,且只显示大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING。
logging.basicConfig()用于为logging日志系统做一些基本配置。
格式:logging.basicConfig(配置参数)
(1)常用参数
参数 名称 |
描述 |
level |
指定日志级别。 |
format |
指定日志格式字符串,即指定日志输出时所包含的字段信息以及它们的顺序。 |
datefmt |
指定日期、时间格式,默认:datefmt="%Y-%m-%d %H:%M:%S"。 |
filename |
指定日志输出目标文件的文件名,指定该设置项后日志信心就不会被输出到控制台了。 |
filemode |
指定日志文件打开模式,默认为'a'。该选项在filename指定时才有效。 |
stream |
指定日志输出目标stream,如sys.stdout、sys.stderr。需要注意stream和filename不能同时出现,否则会引发ValueError异常。 |
style |
指定format格式字符串的风格,可取值为'%'、'{'和'$',默认为'%' |
(2)format格式化字符串的字段
字段名称 |
使用格式 |
描述 |
asctime |
%(asctime)s |
日志事件发生的时间,默认如:2018-05-04 21:48:05,956。 |
created |
%(created)f |
日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值。 |
msecs |
%(msecs)d |
日志事件发生事件的毫秒部分 |
levelname |
%(levelname)s |
该日志记录的文字形式的日志级('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')。 |
levelno |
%(levelno)s |
该日志记录的数字形式的日志级别。 |
name |
%(name)s |
所使用的日志器名称,默认是'root',因为默认使用的是rootLogger。 |
message |
%(message)s |
日志记录的文本内容。 |
pathname |
%(pathname)s |
调用日志记录函数的源码文件的全路径。 |
filename |
%(filename)s |
pathname的文件名部分,包含文件后缀。 |
module |
%(module)s |
filename的名称部分,不包含后缀。 |
lineno |
%(lineno)d |
调用日志记录函数的源代码所在的行号。 |
funcName |
%(funcName)s |
调用日志记录函数的函数名。 |
process |
%(process)d |
进程ID。 |
processName |
%(processName)s |
进程名称。 |
thread |
%(thread)d |
线程ID。 |
threadName |
%(thread)s |
线程名称。 |
(1)在error_test1.py中写入代码
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s:%(message)s',
filename='D:/st07/error/tmp/test.log',
filemode='w')
#日志
logging.debug('this is a debug message')
logging.info('this is a info message')
logging.warning('this is a warning message')
logging.error('this is a error message')
logging.critical('this is a critical message')
#测试代码
try:
print("start")
n=int(input("Please enter a number:"))
share=12/n
print('每一个股东的分红是:{}亿元。'.format(share))
except ValueError as e:
logging.error(e)
except ZeroDivisionError as e:
logging.error(e)
finally:
print("end")
(2)控制台输出
(3)查看test.log日志文件
2018-05-04 22:34:02,591 -error_test1.py[line:7] - DEBUG:this is a debugmessage
2018-05-04 22:34:02,591 -error_test1.py[line:8] - INFO:this is a infomessage
2018-05-04 22:34:02,591 -error_test1.py[line:9] - WARNING:this is awarning message
2018-05-04 22:34:02,591 -error_test1.py[line:10] - ERROR:this is a errormessage
2018-05-04 22:34:02,591 -error_test1.py[line:11] - CRITICAL:this is a critical message
2018-05-04 22:34:06,850 -error_test1.py[line:19] - ERROR:invalid literalfor int() with base 10: '3.5'
(1)在把DEBUG等级日志输出到文件的同时,在控制台只输出ERROR等级日志
在error1.py中写入代码:
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s:%(message)s',
filename='D:/st07/error/tmp/test.log',
filemode='w')
#在控制台输出ERROR等级日志,在logging.basicConfig中的参数配置会成为默认配置
#创建一个logger,定义输出到控制台的log等级开关为ERROR
logger = logging.getLogger()
con = logging.StreamHandler()
con.setLevel(logging.ERROR)
#定义handler的输出格式
format1 = logging.Formatter("%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s: %(message)s")
con.setFormatter(format1)
#将logger添加到handler里面
logger.addHandler(con)
#日志
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
#测试代码
try:
print("start")
n=int(input("Please enter a number:"))
share=12/n
print('每一个股东的分红是:{}亿元。'.format(share))
except ValueError as e:
logging.error(e)
except ZeroDivisionError as e:
logging.error(e)
finally:
print("end")
(2)在控制台输出:
(3)查看test.log日志文件:
2018-05-04 23:05:16,612 -error1.py[line:20] - DEBUG:debug message
2018-05-04 23:05:16,612 -error1.py[line:21] - INFO:info message
2018-05-04 23:05:16,612 -error1.py[line:22] - WARNING:warning message
2018-05-04 23:05:16,612 -error1.py[line:23] - ERROR:error message
2018-05-04 23:05:16,612 -error1.py[line:24] - CRITICAL:critical message
2018-05-04 23:05:46,735 -error1.py[line:33] - ERROR:invalid literal for int() with base 10: '2.5'
(1)logging模块的四大组件
组件名称 |
对应类名 |
描述 |
日志器 |
Logger |
提供了应用程序可一直使用的接口。 |
处理器 |
Handler |
将logger创建的日志记录发送到合适的目的输出。 |
过滤器 |
Filter |
提供了更细粒度的控制工具来决定输出哪条日志记录,丢弃哪条日志记录。 |
格式器 |
Formatter |
决定日志记录的最终输出格式。 |
(2)Logger对象常用方法
方法 |
描述 |
Logger.setLevel() |
设置日志器将会处理的日志消息的最低严重级别。 |
Logger.addHandler() |
为该logger对象添加handler对象。 |
Logger.removeHandler() |
为该logger对象移除handler对象。 |
Logger.addFilter() |
为该logger对象添加filter对象。 |
Logger.removeFilter() |
为该logger对象移除个filter对象。 |
怎样得到一个Logger对象呢?
通常用: logger = logging.getLogger()
logging.getLogger()方法有一个可选参数name,该参数表示将要返回的日志器的名称标识,如果不提供该参数,则其值为'root'。
name相同:只要logging.getLogger(name)中name相同,则返回的Logger实例就是同一个,最后logger的输出遵从后来设置的日志级别。
(3)Handler对象常用方法
方法 |
描述 |
Handler.setLevel() |
设置handler将会处理的日志消息的最低严重级别。 |
Handler.setFormatter() |
为handler设置一个格式器对象。 |
Handler.addFilter() |
为handler添加一个过滤器对象。 |
Handler.removeFilter() |
为handler删除一个过滤器对象。 |
一些常用的Handler子类
Handler |
描述 |
logging.StreamHandler |
将日志消息发送到Stream。 |
logging.FileHandler |
将日志消息发送到磁盘文件,默认情况下文件大小会无限增长。 |
logging.handlers.RotatingFileHandler |
将日志消息发送到磁盘文件,并支持日志文件按大小切割。 |
logging.hanlders.TimedRotatingFileHandler |
将日志消息发送到磁盘文件,并支持日志文件按时间切割。 |
logging.handlers.HTTPHandler |
将日志消息以GET或POST的方式发送给一个HTTP服务器。 |
logging.handlers.SMTPHandler |
将日志消息发送给一个指定的email地址。 |
例如:
con = logging.StreamHandler()
con.setLevel(logging.ERROR)
经常需要将日志消息发送到磁盘文件,并支持日志文件按时间切割:logging.hanlders.TimedRotatingFileHandler的构造函数定义如下:
TimedRotatingFileHandler(filename[,when [,interval [,backupCount]]])
filename是输出日志文件名,when是一个字符串:
“S”:Seconds
“M”: Minutes
“H”: Hours
“D”: Days
“W”: Week day (0=Monday)
“midnight”: Roll over at midnight
interval是指等待多少个单位when的时间后,Logger会自动重建文件(这个文件的创建取决于filename+suffix,若这个文件跟之前的文件有重名,则会自动覆盖掉以前的文件)。
backupCount是保留日志个数,默认的0不会自动删除日志。若设10,则在文件的创建过程中库会判断是否有超过10个,若超过则会从最先创建的开始删除。
(4)Formater对象
Formater对象用于配置日志信息的最终顺序、结构和内容。
例如:
#定义handler的输出格式
format1 =logging.Formatter("%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s: %(message)s")
con.setFormatter(format1)
(5)Filter对象
Filter可以被Handler和Logger用来做比level更细粒度的、更复杂的过滤功能。
(1)需求
(a)要求将所有级别的日志都写入磁盘文件中
(b)all.log文件中记录所有的日志信息
(c)error.log文件中单独记录error及以上级别的日志信息
(d)要求all.log,每秒一个log文件,超过10个log就删除。
代码:
import logging
import logging.handlers
import time
import threading
def log_test():
#1.创建一个logger,设置Log等级总开关
logger = logging.getLogger('mylogger')
logger.setLevel(logging.DEBUG)
#2.设置输出到all.log的参数
f1 = logging.handlers.TimedRotatingFileHandler('D:/st07/error/tmp1/all.log', when='S',
interval=1, backupCount=10)
format1=logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s:%(message)s')
f1.setFormatter(format1)
f1.suffix = "%Y-%m-%d_%H-%M-%S.log"
#3.设置输出到error.log的等级开关和格式
f2 = logging.FileHandler('D:/st07/error/tmp1/error.log')
f2.setLevel(logging.ERROR)
format2 = logging.Formatter("%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s: %(message)s")
f2.setFormatter(format2)
#4.把logger添加到handler里面
logger.addHandler(f1)
logger.addHandler(f2)
#日志
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')
#为了测试,重复构造定时器
global timer
timer = threading.Timer(1, log_test)
timer.start()
#测试(用定时器来实现)
timer = threading.Timer(1, log_test)
timer.start()
注意:filehanlder.suffix的格式,如果设定是天应该写成“%Y-%m-%d.log”,写成其他格式会导致不能删除旧文件。
查看生成的log文件个数:
(2)在error_test1.py写代码:
import logging
# 创建logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.INFO)
logger2 = logging.getLogger('mylogger.child1')
logger2.setLevel(logging.WARNING)
f = logging.FileHandler('D:/st07/error/tmp/all.log',mode='w')
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s:%(message)s')
f.setFormatter(formatter)
logger.addHandler(f)
f1 = logging.FileHandler('D:/st07/error/tmp/some.log',mode='w')
f1.setFormatter(formatter)
logger1.addHandler(f1)
logger2.addHandler(f1)
# 日志
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')
logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')
logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')
打开all.log和some.log,可以看到: