Python日志处理--【logging】
在程序开发完成之后,我们会把它部署到生产环境中去,这时候代码相当于是在一个黑盒环境下运行的,我们只能看到其运行的效果,是不能直接看到代码运行过程中每一步的状态的。在这个环境下,运行过程中难免会在某个地方出现问题,甚至这个问题可能是我们开发过程中未曾遇到的问题。因此,日志记录非常有必要的,任何一款软件如果没有标准的日志记录,都不能算作一个合格的软件。
1、日志级别
首先来了解一下输出日志的等级信息,logging模块共提供了如下等级,每个等级其实都对应了一个数值,列表如下:
| 等级 | 数值 | 
| CRITICAL | 50 | 
| ERROR | 40 | 
| WARNING | 30 | 
| INFO | 20 | 
| DEBUG | 10 | 
| NOTEST | 0 | 
我们自定义日志级别时注意不要和默认的日志级别数值相同,logging 执行时输出大于等于设置的日志级别的日志信息,如设置日志级别是 INFO,则 INFO、WARNING、ERROR、CRITICAL 级别的日志都会输出。
2、logging流程
官方的 logging 模块工作流程图如下:

从上图中我们可以看出看到这几种 Python 类型,Logger、LogRecord、Filter、Handler、Formatter。
类型说明:
Logger:日志,暴露函数给应用程序,基于日志记录器和过滤器级别决定哪些日志有效。
LogRecord :日志记录器,将日志传到相应的处理器处理。
Handler :处理器, 将(日志记录器产生的)日志记录发送至合适的目的地。
Filter :过滤器, 提供了更好的粒度控制,它可以决定输出哪些日志记录。
Formatter:格式化器, 指明了最终输出中日志记录的布局。
大体流程:
- 判断 Logger 对象对于设置的级别是否可用,如果可用,则往下执行,否则,流程结束。
- 创建 LogRecord 对象,如果注册到 Logger 对象中的 Filter 对象过滤后返回 False,则不记录日志,流程结束,否则,则向下执行。
- LogRecord 对象将 Handler 对象传入当前的 Logger 对象,(图中的子流程)如果 Handler 对象的日志级别大于设置的日志级别,再判断注册到 Handler 对象中的 Filter 对象过滤后是否返回 True 而放行输出日志信息,否则不放行,流程结束。
- 如果传入的 Handler 大于 Logger 中设置的级别,也即 Handler 有效,则往下执行,否则,流程结束。
- 判断这个 Logger 对象是否还有父 Logger 对象,如果没有(代表当前 Logger 对象是最顶层的 Logger 对象 root Logger),流程结束。否则将 Logger 对象设置为它的父 Logger 对象,重复上面的 3、4 两步,输出父类 Logger 对象中的日志输出,直到是 root Logger 为止。
3、日志输出格式
4、基本使用
logging 使用非常简单,使用 basicConfig() 方法就能满足基本的使用需要,如果方法没有传入参数,会根据默认的配置创建Logger 对象,默认的日志级别被设置为 WARNING,默认的日志输出格式如上图,该函数可选的参数如下表所示。
| 参数名称 | 参数描述 | 
| filename | 日志输出到文件的文件名 | 
| filemode | 文件模式,r[+]、w[+]、a[+] | 
| format | 日志输出的格式 | 
| datefat | 日志附带日期时间的格式 | 
| level | 设置日志输出级别 | 
| stream | 定义输出流,用来初始化 StreamHandler 对象,不能和 filename 参数一起使用,否则会ValueError 异常 | 
| style | 格式占位符,默认为 "%" 和 “{}” | 
| handles | 定义处理器,用来创建 Handler 对象,不能和 filename 、stream 参数一起使用,否则也会抛出 ValueError 异常 | 
示例代码如下:
import logging
logging.basicConfig()
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message') 
输出结果如下:
WARNING:root:This is a warning message
ERROR:root:This is an error message
CRITICAL:root:This is a critical message
传入常用的参数,示例代码如下(这里日志格式占位符中的变量放到后面介绍):
import logging
logging.basicConfig(filename="test.log", filemode="w", format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%d-%M-%Y %H:%M:%S", level=logging.DEBUG)
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')
生成的日志文件 test.log ,内容如下:
13-10-18 21:10:32 root:DEBUG:This is a debug message
13-10-18 21:10:32 root:INFO:This is an info message
13-10-18 21:10:32 root:WARNING:This is a warning message
13-10-18 21:10:32 root:ERROR:This is an error message
13-10-18 21:10:32 root:CRITICAL:This is a critical message
但是当发生异常时,直接使用无参数的 debug()、info()、warning()、error()、critical() 方法并不能记录异常信息,需要设置 exc_info 参数为 True 才可以,或者使用 exception() 方法,还可以使用 log() 方法,但还要设置日志级别和 exc_info 参数。
import logging
logging.basicConfig(filename="test.log", filemode="w", format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%d-%M-%Y %H:%M:%S", level=logging.DEBUG)
a = 5
b = 0
try:
    c = a / b
except Exception as e:
    # 下面三种方式三选一,推荐使用第一种
    logging.exception("Exception occurred")
    logging.error("Exception occurred", exc_info=True)
    logging.log(level=logging.DEBUG, msg="Exception occurred", exc_info=True)
参考:https://juejin.im/post/5bc2bd3a5188255c94465d31#heading-3 

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号