python自带的记录日志模块 logging 非常强大,但是每次写程序都要写很多东西来配置使用,体验不怎么友好,花时间封装在一个文件里面,用的时候直接调用,并且提供配置接口保留其强大的功能还是非常有必要的。
logging介绍
Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP,Socket等,甚至可以自己实现具体的日志记录方式。
logging模块与log4j的机制是一样的,只是具体的实现细节不同。模块提供logger,handler,filter,formatter。
- logger:提供日志接口,供应用代码使用。
- handler:将日志记录(log record)发送到合适的目的地(destination),比如文件,socket,cmd等。一个logger对象可以通过addHandler方法添加0到多个handler,每个handler又可以定义不同日志级别,以实现日志分级过滤显示。每个handler还可以单独设置自己的formatter格式。
- filter:提供一种优雅的方式决定一个日志记录是否发送到handler。
- formatter:指定日志记录输出的具体格式。
与log4j类似,logger,handler和日志消息的调用可以有具体的日志级别(Level),只有在日志消息的级别大于logger和handler的级别才会呈现。
默认的日志级别设置为WARNING
(日志级别等级CRITICAL
> ERROR
> WARNING
> INFO
> DEBUG
> NOTSET
), 小于WARNING级别的日志都不输出, 大于等于WARNING级别的日志都会输出。
更多可以自己搜索一下。
封装成log.py
源码在github上有:python_log
1 | #!/usr/bin/env python |
例子
用的时候把log.py丢到工程目录然后import进来初始化一个Log对象即可。
如果全部使用默认配置(具体值请看Log类的init函数):1
2
3
4
5
6
7# tmp.py
import log
log = log.Log()
log.debug('hello, world')
log.info('hello, world')
log.error('hello, world')
log.critical('hello, world')
得到结果:
在命令行跟文件里面分别记录运行日志,命令行呈现大于DEBUG级别的记录,文件记录大于INFO级别的记录。文件名跟主程序的py名字一样,这里是tmp.log
。里面内容:1
2
3
4
5
6[2016-05-29 17:17:05] tmp.py line:6 INFO hello, world
[2016-05-29 17:17:05] tmp.py line:7 ERROR hello, world
[2016-05-29 17:17:05] tmp.py line:8 CRITICALhello, world
[2016-05-29 17:17:49] tmp.py line:6 INFO hello, world
[2016-05-29 17:17:49] tmp.py line:7 ERROR hello, world
[2016-05-29 17:17:49] tmp.py line:8 CRITICALhello, world
cmd显示运行结果:1
2
3
4
5[17:17:05] tmp.py line:5 DEBUG hello, world
[17:17:05] tmp.py line:6 INFO hello, world
[17:17:05] tmp.py line:7 ERROR hello, world
[17:17:05] tmp.py line:8 CRITICALhello, world
Hit any key to close this window...
里面的内容符合对文件跟cmd的level级别筛选规则,显示的格式也分别符合Log类
init默认初始化参数的formatter设置的规则。
如果要更改设置,直接调用log.set_logger
就可以了。一般来说很少会有更改设置的情况,都是直接初始化就一直用到结束。有一种情况就是给出一个可以调整log level的级别的配置接口。这样程序运行的过程中,遇到bug用户可以调整日志级别,然后把debug日志记录获取到发给开发人员分析。
另外,封装的log.py比原来的logging模块多了一个trace接口。可以打印exception的详细信息。具体用法可以看封装的文件里边的例子。
其他
1. formatter配置
下面是formatter用到的匹配规则,其中asctime还可以进一步配置:命令行通过cmddatefmt
、文件日志通过filedatefmt
,具体写法可参照Log类的初始化函数。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17+---------------------+-----------------------------------------------------------------------------
| %(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. Use set_logger to change settings
1 | # Change limit size in bytes of default rotating action |