python日志模块笔记
前言
在应用中记录日志是程序开发的重要一环,也是调试的重要工具。但却很容易让人忽略。之前用flask写的一个服务就因为没有处理好日志的问题导致线上的错误难以察觉,修复错误的定位也很困难。最近恰好有时间可以梳理一下python日志的功能,下面是一点笔记。
使用
python标准库中提供了记录日志的方案。
import logging
from logging.config import dictConfig
logger = logging.getLogger(__name__)
# 定义格式
formatter = logging.Formatter(fmt='%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
# 定义日志处理器
streamHdl = logging.StreamHandler()
# 设定日志级别
streamHdl.setLevel(logging.DEBUG)
# 设定日志格式
streamHdl.setFormatter(formatter)
# 给日志器添加日志处理器
logger.addHandler(streamHdl)
# 记录日志
logger.debug()
logger.info()
logger.warning()
logger.error()
logger.critical()
从上面的演示这个模块的使用是比较简单的。但在应用中深入使用有些需要注意的地方:
parent logger / child logger
在多模块程序中使用多个模块是很常见的,被引用模块中的日志对象容易让人迷惑。我们知道一个应用有一个唯一的文件入口,如果这个入口文件中定义了logger,那这个logger就是parent logger, 其中被导入的模块中定义的logger就是child logger, 与我们常见的在一个模块中实例化使用不同,在每一个需要记录日志的地方都需要产生一个logger,然后进行日志记录操作。每个模块内部所记录的日志根据每个logger的配置信息对日志进行操作,然后根据该logger是否反向传递到parent logger进一步操作。反向传递到parent logger之后,依旧像普通的logger一样对日志进行处理。
日志的配置
https://docs.python.org/3/howto/logging.html#configuring-logging
每个logger都可以通过ini文件、yarm文件、对象等形式进行配置,这里主要讲以字典形式进行的配置。
logging_config = dict(
version=1,
formatters={
'f': {'format':
'%(asctime)s000000 %(name)-12s %(levelname)-8s %(message)s'}
},
handlers={
'h': {'class': 'logging.StreamHandler',
'formatter': 'f',
'level': logging.DEBUG}
},
root={
'handlers': ['h'],
'level': logging.DEBUG,
},
)
dictConfig(logging_config)
当在一个文件中使用dictConfig,就给该文件的logger定义了配置。
异常的捕捉
logger.error()与logger.exception()之间的区别在于error()只会打印一句话,而exception()则会将异常的错误栈都会打印出来。对于出现代码异常的地方,可以使用exception()用作记录。
普通日志直接使用logging模块来记录,应用内不处理日志的去向,作为事件流统一输出到标准输出,采用第三方日志采集工具进行捕获和处理。但也不能太绝对,如果外部收集日志的程序缺少对日志级别分类,或者对异常记录缺少必要的支持,就需要内置的模块进行处理。
常用的内置handler
https://docs.python.org/3/howto/logging.html#useful-handlers
参考
https://12factor.net/logs
https://docs.python.org/3/howto/logging.html
https://docs.python.org/3/howto/logging-cookbook.html