文章目录

🧁logging的使用

  • 🧁简单使用
  • 🧁设置等级
  • 🧁设置格式化
  • 内置变量
  • 自定义变量
  • 🧁应用例子

本文对

logging的使用进行粗浅的解释,可以满足大多数场景的使用,文末也附带了例子可供参考。更多的高大上的用法可自行研究,也希望能一起探讨。

🧁logging的使用

通常我们在写代码时,需要查看或跟踪某个变量或者输出某些信息,都是直接使用print()在控制台直接输出,这样可以很便捷的看到我们想要的信息。但是如果某个变量的随时变化的,仅仅通过控制台,我们很难看到其变化趋势,或者是代码代码运行过后,在某个时间点又想要查看之前的输出,那么这时就需要将输出持久化。

logging是一个日志包,可以满足我们对所需内容的跟踪记录包括打印在控制台与文件持久化。

🧁简单使用

import logging

logging.debug('这是一条debug日志')
logging.info('这是一条info日志')
logging.warning('这是一条warning日志')
logging.error('这是一条error日志')

WARNING:root:这是一条warning日志
ERROR:root:这是一条error日志

从控制台可以看到输出的日志只有上面两条,因为默认的输出日志等级是warning,可以通过设置日志等级来选择过滤的日志。

🧁设置等级

import logging

logging.basicConfig(filename=None, filemode='a', level=logging.DEBUG)
logging.debug('这是一条debug日志')
logging.info('这是一条info日志')
logging.warning('这是一条warning日志')
logging.error('这是一条error日志')

#DEBUG:root:这是一条debug日志
#INFO:root:这是一条info日志
#WARNING:root:这是一条warning日志
#ERROR:root:这是一条error日志

预定义的日志等级代表的数值:

级别 数值
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0

通过basicConfig设置日志等级level,当filename为None时,会将过滤后的日志打印在控制台,如果是一个文件名(比如:test.log或test.txt),则不会打印而是保存成文件。

🧁设置格式化

从上面的代码及输出中可以看到,输出的日志与我们传入的字符串有一些差异。 比如logging.info('这是一条info日志')的输出是INFO:root:这是一条info日志。 其中INFO和root是默认输出的内容,可通过设置格式来修改日志格式和内容。

INFO:日志等级 root:https://docs.python.org/3/howto/logging.html#advanced-logging-tutorial

内置变量

https://docs.python.org/zh-cn/3/library/logging.html#logrecord-attributes

可以通过格式化进行日志输出。 常用的有:

  • args:不需要用户进行格式化。合并到 msg 以产生 message 的包含参数的元组,或是其中的值将被用于合并的字典(当只有一个参数且其类型为字典时)。
  • msg:不需要用户进行格式化。在原始日志记录调用中传入的格式字符串。 与 args 合并以产生 message,或是一个任意对象
  • message:记入日志的消息,即 msg % args 的结果。
  • asctime:表示该条日志记录是何时被创建的。‘2022-03-31 14:22:41,962’ (逗号之后的数字为时间的毫秒部分)
  • filename:pathname 的文件名部分。
  • funcName:函数名包括调用日志记录。
  • levelname:消息文本记录级别(‘DEBUG’,‘INFO’,‘WARNING’,‘ERROR’,‘CRITICAL’)。
  • lineno:发出日志记录调用所在的源行号(如果可用)。
  • name:用于记录调用的日志记录器名称。
import logging

FORMAT = '%(asctime)s %(filename)s %(funcName)s %(levelname)s %(lineno)s %(message)s '
logging.basicConfig(filename=None, filemode='a', format= FORMAT, level=logging.DEBUG)

logging.debug('这是一条debug日志')
logging.info('这是一条info日志')
logging.warning('这是一条warning日志')
logging.error('这是一条error日志')

def foo():
    logging.info('这是一条来自foo函数的info日志')
foo()

#2022-03-31 16:22:17,561 a0.py <module> DEBUG 8 这是一条debug日志 
#2022-03-31 16:22:17,561 a0.py <module> INFO 9 这是一条info日志 
#2022-03-31 16:22:17,561 a0.py <module> WARNING 10 这是一条warning日志
#2022-03-31 16:22:17,562 a0.py <module> ERROR 11 这是一条error日志
#2022-03-31 16:22:17,562 a0.py foo INFO 14 这是一条来自foo函数的info日志

FORMAT可以参考上面的变量按需求组织输出格式。

自定义变量

可通过传入一个字典,按找需求输出日志。有时候会需要使用到多个不同的自定义格式变量,可以传入一个字典,其中的key对应自定义变量名。

import logging

FORMAT = '%(asctime)s epochs:%(epochs)s lr:%(lr)s loss:%(loss)s %(message)s '
logging.basicConfig(filename=None, filemode='a', format= FORMAT, level=logging.DEBUG)

d = {
    'epochs': '30/10000',
    'lr': 1e-5,
    'loss': 0.0024788384325802326
}
logging.info('自定义', extra=d)

#2022-03-31 16:34:46,564 epochs:30/10000 lr:1e-05 loss:0.0024788384325802326 自定义

🧁应用例子

# custom_logger.py
import logging

def set_logging(name=None, level=logging.WARNING, verbose=True):
    # 设置日志等级并返回实例。可同时保存到文件和打印到控制台
    logger = logging.getLogger(name)
    logger.setLevel(level=level)

    FORMAT = '%(asctime)s [%(name)s] %(filename)s[line:%(lineno)d] %(levelname)s: %(message)s'
    formatter = logging.Formatter(FORMAT)
    # 保存到文件
    fh = logging.FileHandler(filename='debug/test.txt', encoding='utf-8', mode='a')  # encoding避免中文保存到文件出现乱码
    fh.setFormatter(formatter)
    logger.addHandler(fh)

    if verbose:
        # 打印到控制台
        sh = logging.StreamHandler()
        sh.setFormatter(formatter)
        logger.addHandler(sh)

    return logger

LOGGER = set_logging(name='test', level=logging.INFO, verbose=True)


if __name__ == '__main__':
    LOGGER.info('这是一条日志')
    # 2022-04-30 13:47:24,663 [test] custom_logger.py[line:29] INFO: 这是一条日志