当前位置:   article > 正文

py logging 日志模块

py logging

一. 快速开始

官方文档大而全, 见 [1].
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
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
'
运行

使用步骤通常为:
创建 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)
  • 1

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

不同的输出流位置

  • 控制台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
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
'
运行

六. 如何查看三方包的日志

shap 包为例, 创建 logger 并记录不同等级的日志.

log = logging.getLogger('shap')
log.info("num_full_subsets = {0}".format(num_full_subsets))
log.debug("samples_left = {0}".format(samples_left))
  • 1
  • 2
  • 3

因为 默认级别是 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

参考

  1. 官方doc, logging
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/963141
推荐阅读
相关标签
  

闽ICP备14008679号