日志模块 logging
默认情况下Python的logging模块的日志级别是warning,默认输出到标准输出stdout 默认的日志格式为 日志级别:Logger名称:用户输出消息; 设置logging的默认格式及输出位置使用basicConfig方法。
一、 logging模块的常用方法
1. basicConfig(**kwargs)
配置日志基本配置;参数可以是如下:
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”,一般默认。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别;默认是warnning
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open('test.log','w')),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
style 这个再补充吧
handlers 如果指定的话,这应该是一个已经创建的程序,将其添加到root handler。在没有格式化指定列表中的任何处理程序将被分配在这个函数创建格式化程序。
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用户输出的消息
2. disable(level)
关闭指定级别及以下级别的日志;
3. logging.debug()
记录debug级别的日志;
4. logging.info()
记录info级别日志;
5. logging.warning()
记录warning级别日志;
6. logging.error()
记录error级别日志;
7. logging.critical()
记录critical级别日志;
8. logging.getLogger()
模块级别的函数logging.getLogger('name'),返回一个logger对象,如果没有指定名字将返回root logger;
例如: logging.getLogger('mylogger')
9. logging.FileHandler('/tmp/test.log')
创建一个handler,用于写入日志文件;
10. logging.StreamHandler()
创建一个handler,用于输出到控制台;
二、 案例
案例一: 输出日志在文件和终端
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging #默认输出为stdout logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message') #设置默认输出 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')
案例二:同时输出在多个位置
如果这个案例看不懂,先看下面第三部分;
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging logger = logging.getLogger() # 创建一个handler fh,用于写入日志文件 fh = logging.FileHandler('test.log') # 再创建一个handler ch,用于输出到控制台 ch = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 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')
可以看到,同时输出在stdout和文件;
案例三:
import logging logger1=logging.getLogger('mylogger') logger2=logging.getLogger('mylogger') print(logger1) # print(logger2) # logger1.setLevel('DEBUG') print(logger1) # print(logger2) #
上面案例可以发现,name和logger实例是一一对应的。即使赋给了logger1/logger2,更改其中一个,另一个也会跟着改变;
三、 日志模块解析
-
logging.basicConfig()
用默认日志格式(Formatter)为日志系统建立一个默认的流处理器(StreamHandler),设置基础配置(如日志级别等)并加到root logger(根Logger)中;
-
logging.getLogger()
返回一个logger对象,如果没有指定名字将返回root logger; 另外,创建的logger都是root logger的“孩子”;这里mylogger属于root logger的子孙,继承root logger的属性(日志级别、Handler、Filter设置),除非设置了mylogger的属性。 可以通过Logger.setLevel(lel)、Logger.addHandler(hdlr)、Logger.removeHandler(hdlr)、Logger.addFilter(filt)、Logger.removeFilter(filt) 来设置mylogger的日志级别、Handler、Filter。
-
logging组件
Logger: 记录器,暴露了应用程序代码能直接使用的接口。 Handler: 处理器,将(记录器产生的)日志记录发送至合适的目的地。 Filter: 过滤器,提供了更好的粒度控制,它可以决定输出哪些日志记录。 Formatter: 格式化器,指明了最终输出中日志记录的格式。
1. logger
Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取则自动创建并使用root Logger)。可以通过Logger.setLevel(level)或logging.basicConfig()指定最低的日志级别。
Logger可以包含一个或多个Handler和Filter,即Logger与Handler或Fitler是一对多的关系; 一个Logger实例可以新增多个Handler,一个Handler可以新增多个格式化器或多个过滤器,而且日志级别将会继承。
创建方法: logger = logging.getLogger(logger_name)
创建Logger实例后,可以使用以下方法进行日志级别设置,增加处理器Handler:
- logger.setLevel(logging.ERROR) # 设置日志级别为ERROR,即只有日志级别大于等于ERROR的日志才会输出
- logger.addHandler(handler_name) # 为Logger实例增加一个处理器
- logger.removeHandler(handler_name) # 为Logger实例删除一个处理器
2. handler
Handler处理器类型有很多种,比较常用的有三个,StreamHandler,FileHandler,NullHandler,详情可以查看官网。
创建handler: logging.FileHandler('/tmp/test.log',mode='a', encoding=None, delay=False) logging.StreamHandler() NullHandler类位于核心logging包,不做任何的格式化或者输出。本质上它是个“什么都不做”的handler,由库开发者使用。
创建StreamHandler之后,可以通过使用以下方法设置日志级别,设置格式化器Formatter,增加或删除过滤器Filter:
- ch.setLevel(logging.WARN) # 指定日志级别,低于WARN级别的日志将被忽略
- ch.setFormatter(formatter_name) # 设置一个格式化器formatter
- ch.addFilter(filter_name) # 增加一个过滤器,可以增加多个
- ch.removeFilter(filter_name) # 删除一个过滤器
3. formatter
使用Formatter对象设置日志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d %H:%M:%S。
创建方法: formatter = logging.Formatter(fmt=None, datefmt=None) 其中,fmt是消息的格式化字符串,datefmt是日期字符串。如果不指明fmt,将使用'%(message)s'。如果不指明datefmt,将使用ISO8601日期格式。
4. Filer
日志过滤,只有满足过滤规则的日志才会输出。
创建方法: filter = logging.Filter(name='')
例如:
filter = logging.Filter('mylogger') # 使用该filter的handler将只记录mylogger开头的日志;
fh.addFilter(filter)
ch.addFilter(filter)