程序开发过程中,很多程序都有记录日志的需求,并且日志包含的信息有正常的程序访问日志,还可能有错误、警告等信息输出,Python 的 logging 模块提供了标准的日志接口,可以通过它存储各种格式的日志,日志记录提供了一组便利功能,用于简单的日志记录用法。
下面介绍一下logging的简单用法,能够满足日常的使用。
日志模块解析
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
日志级别等级排序:critical > error > warning > info > debug
- debug : 详细信息,一般只在调试问题时使用,打印全部的日志( notset 等同于 debug )。
- info : 证明事情按预期工作,打印 info, warning, error, critical 级别的日志。
- warning : 某些没有预料到警告信息,或者在将来可能会出现的问题提示。例如:磁盘空间不足,但是软件还是会照常运作,打印 warning, error, critical 级别的日志。
- error : 由于更严重的问题,软件已不能执行一些功能了,打印 error, critical 级别的日志。
- critical : 严重错误,表明软件已不能继续运行了,打印 critical 级别。
默认等级是WARNING,默认输出到控制台。
级别越高打印的日志越少,反之亦然。
2. 日志级别设置
logging.getLogger()
模块级别的函数logging.getLogger(‘name’),返回一个logger对象,如果没有指定名字将返回root logger;
Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取则自动创建并使用root Logger)。可以通过Logger.setLevel(level)或logging.basicConfig()指定最低的日志级别。
import logging
logger = logging.getLogger() #获得logger对象
logger.setLevel(logging.INFO) #设置日志级别
3. 日志处理器
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) # 删除一个过滤器
4. formatter
使用Formatter对象设置日志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d %H:%M:%S。
创建方法:
formatter = logging.Formatter(fmt=None, datefmt=None)
其中,fmt是消息的格式化字符串,datefmt是日期字符串。如果不指明fmt,将使用’%(message)s’。如果不指明datefmt,将使用ISO8601日期格式。
5. Filter
日志过滤,只有满足过滤规则的日志才会输出。
创建方法:
filter = logging.Filter(name='')
例如:
filter = logging.Filter(‘mylogger’) # 使用该filter的handler将只记录mylogger开头的日志;
fh.addFilter(filter)
ch.addFilter(filter)
6. logging.basicConfig()
配置日志基本配置;参数可以是如下:
-
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参数会被忽略。
-
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用户输出的消息
6. 日志记录模板
模板1
import logging
logger = logging.getLogger() #创建logger对象
logger.setLevel(logging.INFO) #设置日志权限
log_file = '/temp/test/log.txt' #日志文件路径
fh = logging.FileHandler(log_file) #生成文件处理器对象
sh = logging.StreamHandler() #生成控制台处理器对象
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') #设置日志模式
fh.setFormatter(formatter) #添加模式
ch.setFormatter(formatter) #添加模式
logger.addHandler(fh) #添加文件处理器
logger.addHandler(sh) #添加控制台处理器
logger.info('输出日志记录')
#同时在控制台和文件输出
模板2
import loggering
#通过basicConfig设置权限,格式,日志存储路径
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.txt',
filemode='w')
#打印日志,输出为文件
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')