logging日志模块
logging模块,干什么用
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() and critical()
5个级别,级别依次升高。下面来具体看下:
DEBUG 调试 10
INFO 正常 20
WARNING 警告 30
ERROR 错误 40
CRITICAL 严重 50
默认级别为warning,默认打印到终端
import logging
logging.debug('调试debug')
logging.info('消息info')
logging.warning('警告warn')
logging.error('错误error')
logging.critical('严重critical')
'''
WARNING:root:警告warn
ERROR:root:错误error
CRITICAL:root:严重critical
'''
logging.basicConfig(filename='example.log',
level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s %(filename)s %(funcName)s %(lineno)s',
datefmt='%Y/%m/%d %H:%M:%S %p')
'''
level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说大于等于INFO级别的日志才会被纪录到文件里,
如果希望纪录debug的日志,那把日志级别改成DEBUG就行了。第二次运行会以追加模式接着写。
'''
logging.debug('This message should go to the log file') # 这里等级低于INFO不会被输出
logging.info('welcome come !') # 高于等于info才会输出
logging.warning("user [cc] attempted wrong password more than 3 times")
# 结果: WARNING:root:user [cc] attempted wrong password more than 3 times
python中时间日期格式化符号:
- %y 两位数的年份表示(00-99)
- %Y 四位数的年份表示(000-9999)
- %m 月份(01-12)
- %d 月内中的一天(0-31)
- %H 24小时制小时数(0-23)
- %I 12小时制小时数(01-12)
- %M 分钟数(00=59)
- %S 秒(00-59)
- %a 本地简化星期名称
- %A 本地完整星期名称
- %b 本地简化的月份名称
- %B 本地完整的月份名称
- %c 本地相应的日期表示和时间表示
- %j 年内的一天(001-366)
- %p 本地A.M.或P.M.的等价符
- %U 一年中的星期数(00-53)星期天为星期的开始
- %w 星期(0-6),星期天为星期的开始
- %W 一年中的星期数(00-53)星期一为星期的开始
- %x 本地相应的日期表示
- %X 本地相应的时间表示
- %Z 当前时区的名称
- %% %号本身
format参数格式化
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用户输出的消息
日志输出的流程(画图理解)
日志的handle种类
一、StreamHandler
流handler——包含在logging模块中的三个handler之一。
能够将日志信息输出到sys.stdout, sys.stderr 或者类文件对象(更确切点,就是能够支持write()和flush()方法的对象)。
只有一个参数:
日志信息会输出到指定的stream中,如果stream为空则默认输出到sys.stderr。
二、FileHandler
logging模块自带的三个handler之一。继承自StreamHandler。将日志信息输出到磁盘文件上。
构造参数:
模式默认为append,delay为true时,文件直到emit方法被执行才会打开。默认情况下,日志文件可以无限增大。
三、NullHandler
空操作handler,logging模块自带的三个handler之一。
没有参数。
四、WatchedFileHandler
位于logging.handlers模块中。用于监视文件的状态,如果文件被改变了,那么就关闭当前流,重新打开文件,创建一个新的流。由于newsyslog或者logrotate的使用会导致文件改变。这个handler是专门为linux/unix系统设计的,因为在windows系统下,正在被打开的文件是不会被改变的。
参数和FileHandler相同:
五、RotatingFileHandler
位于logging.handlers支持循环日志文件。
class logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0)
参数maxBytes和backupCount允许日志文件在达到maxBytes时rollover.当文件大小达到或者超过maxBytes时,就会新创建一个日志文件。上述的这两个参数任一一个为0时,rollover都不会发生。也就是就文件没有maxBytes限制。backupcount是备份数目,也就是最多能有多少个备份。命名会在日志的base_name后面加上.0-.n的后缀,如example.log.1,example.log.1,…,example.log.10。当前使用的日志文件为base_name.log。
六、TimedRotatingFileHandler
定时循环日志handler,位于logging.handlers,支持定时生成新日志文件。
class logging.handlers.TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False)
参数when决定了时间间隔的类型,参数interval决定了多少的时间间隔。如when=‘D’,interval=2,就是指两天的时间间隔,backupCount决定了能留几个日志文件。超过数量就会丢弃掉老的日志文件。
when的参数决定了时间间隔的类型。两者之间的关系如下:
utc参数表示UTC时间。
七、其他handler——SocketHandler、DatagramHandler、SysLogHandler、NtEventHandler、SMTPHandler、MemoryHandler、HTTPHandler
这些handler都不怎么常用,所以具体介绍就请参考官方文档 其他handlers
下面使用简单的例子来演示handler的使用:
例子一——不使用配置文件的方式(StreamHandler):
输出到控制台的结果:
例子二——使用配置文件的方式(TimedRotatingFileHandler) :
log.conf 日志配置文件:
获取logger方法:
配置logger并且调用:
控制台和日志文件中都会输出:
记录日志到控制台,和文件
import logging
from logging import handlers
# 步骤1:创建一个收集器对象,并且设置等级.
logger = logging.getLogger("阿登的日志")
logger.setLevel(10) # 设置全局的日志等级
#步骤2:设置handle:一个输出到控制台,一个输出到日志
ch = logging.StreamHandler()
fh = handlers.RotatingFileHandler(filename="size_01.log",mode="a",maxBytes=1024*1024*2,backupCount=4,encoding="utf-8")
# 步骤3: 为所有handle设置等级
ch.setLevel(10)
fh.setLevel(10)
# 步骤4: 设置formatter
formatter = logging.Formatter ("'%(asctime)s - [%(levelname)s] - [filename]:%(filename)s - [name]:%(name)s - [line]:%(lineno)d -[def]:%(funcName)s - [msg]: %(message)s'")
# 步骤5: formatter组件和所有handle绑定
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# 步骤6: handle添加到logger
logger.addHandler(ch)
logger.addHandler(fh)
# 调用logger
logger.debug("this is debug13")
yaml配置日志
import logging
from logging import config
import yaml
with open(r"data.yaml", "r",encoding="utf-8") as f:
datas = yaml.load(f,Loader=yaml.FullLoader) # Loader=yaml.FullLoader 去除警告
print(datas)
pass
config.dictConfig(datas)
logger = logging.getLogger('adeng')
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')
配置文件data.yaml
version: 1
formatters:
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
console_err:
class: logging.StreamHandler
level: ERROR
formatter: simple
stream: ext://sys.stderr
file:
class: logging.FileHandler
level: DEBUG
formatter: simple
filename: adeng_01.log
encoding: utf-8
loggers:
adeng:
level: DEBUG
handlers: [console,file]
propagate: yes
root:
level: DEBUG
handlers: [console_err]
未完待续