文章目录
- 一. 快速开始
- 二. Logger
- RootLogger
- 三. Handler
- 缺省handler
- 不同的输出流位置
- 四. Formatter
- 五. 多模块logger如何组织
- 例子
- 六. 如何查看三方包的日志
- 参考
一. 快速开始
官方文档大而全
logging 是 python 自带的 日志模块.
import logging
logging.basicConfig(format='%(asctime)s - [%(levelname)s] - %(message)s',level=logging.INFO)
logging.info("hello")
"""
2019-05-26 20:22:36,579 - [INFO] - hello
"""
使用步骤通常为:
创建 logger -> 创建 handler 并定义 formatter -> 给 logger 添加 handler.
当使用默认全局 logger 时, 设置项为:
logging.basicConfig(**kwargs)
用来设置想要的输出效果.
- format
如%(asctime)s - %(name)s - %(filename)s:%(lineno)s - [%(levelname)s] - %(message)s
- level
日志输出级别阈值. 默认为 warning. 级别采用整数标识, DEBUG=10, INFO=20 . - stream
默认是 标准错误流sys.stderr
(控制台显示为砖红色), 可以改为标准输出流sys.stdout
(标准黑色).
二. Logger
-
logging.getLogger(name=__name__)
不传参数时, 会返回默认的root
logger, level = WARNING. -
logging.info(msg, *args, **kwargs)
msg中有占位符, args参数依次与之对应.
如
logger.log('hi %s, you are no.%d',yichu, 321)
py3后, 支持 f"xx{var}xx"
的写法, 可替代上行写法.
RootLogger
存在一个全局的默认logger, 是一个 RootLogger 实例, 直接 logging.info()
时就会使用该logger.
- class RootLogger(Logger), 可以看到是 Logger 子类.
其自带一个 StreamHandler 实例, 其级别是 NOTSET = 0, 对应标准错误流.
三. Handler
如果说 logger 是记录员, 负责记录内容, handler 则用于明确 记录位置及格式.
handler 也有 logLevel, 若 logger 级别低于 handler 级别, 照样不会输出.
图: 附一张官网的图, 较直观
- logging.Handler.
setFormatter(self, fmt:Formatter)
缺省handler
一个 logger 可以绑定若干个 handler, 当不分配时, 会递归查找 父logger, 用它的 handler.
# 如果当前 logger 没有对应的 handler, 那么就递归用 父类logger对象的 handler
while c:
for hdlr in c.handlers:
if record.levelno >= hdlr.level:
hdlr.handle(record)
c = c.parent
不同的输出流位置
- 控制台handler
logging.StreamHandler() - 文件handler
logging.FileHandler('xx_log.txt',, encoding="utf-8")
日志文件可以由 logging 包动态创建, 但其所在目录必需保证已经存在.
注意utf避免中文乱码。默认是追加模式.
四. Formatter
formatter = logging.Formatter(format:str)
, 常用变量有:
- filename, 源文件名
- lineno, 源文件内的行号
- name, logger name
- levelname, 大写的日志级别, IFO, DEBUG 等
- message, 日志正文
常用搭配:
'%(name)s - [%(levelname)s] - %(message)s'
'%(filename)s:%(lineno)s: %(name)s - [%(levelname)s] - %(message)s'
五. 多模块logger如何组织
项目开发中, 自己会有若干个模块,记为 self_A,self_B; 同时还有大量三方包, 如 numba, tensorflow.
那么,
Q:如何给不同的模块设置不同的输出级别, 有的放矢 地打日志呢?
只建 logger 和定义level是不够的, 还要配上各自的 handler, 见下:
例子
import logging
con_han = logging.StreamHandler()
con_han.setLevel(logging.DEBUG)
formatter=logging.Formatter('%(name)s - [%(levelname)s] - %(message)s')
con_han.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(con_han)
logger.debug("I'm debug")
"""
__main__ - [DEBUG] - I'm debug
"""
六. 如何查看三方包的日志
以 shap 包为例, 创建 logger 并记录不同等级的日志.
log = logging.getLogger('shap')
log.info("num_full_subsets = {0}".format(num_full_subsets))
log.debug("samples_left = {0}".format(samples_left))
因为 默认级别是 warning, 所以信息出不来, 那就需要下面的代码啦:
con_han = logging.StreamHandler()
con_han.setLevel(logging.DEBUG)
shap_logger = logging.getLogger('shap')
shap_logger.setLevel(logging.DEBUG)
shap_logger.addHandler(con_han)
参考
- 官方doc, logging