您的位置:首页 > 娱乐 > 明星 > Python自带日志库实现springboot彩色效果

Python自带日志库实现springboot彩色效果

2024/10/5 20:16:56 来源:https://blog.csdn.net/weixin_45411898/article/details/142073377  浏览:    关键词:Python自带日志库实现springboot彩色效果

整体目标

在这里插入图片描述

涉及的库均为Python3自带库实现

  • logging
  • sys
  • enum

终端显示彩色基本原理参考👉Terminal里的颜色的那些事

Python打印日志可以直接借用logging自带的库实现,但是默认的打印实在太丑了,长下面这样

在这里插入图片描述

这只是一条日志看着还好比较清爽,如果多了之后可想而知,大片红色看着由多么糟糕,借鉴SpringBoot的处理怎么做到SpringBoot那样的彩色日志输出呢?

在这里插入图片描述

这里突然想起来,Java自带的日志框架(JUL)打印也是一片红色,可能原生的东西都比较呆正。

日志框架的组成

日志框架无论哪种语言基本都是遵循一样的做法,包括以下组件:

  • Logger:日志记录器,用于记录打印日志,我们操作的就是这个对象
  • Handler:处理器,有些也叫Appender,就是实际处理日志记录的东西,比如说我们生成一条日志字符串,这个字符串是输出到控制台,还是输出到文件呢?或者说两者都输出呢?这就是处理器做的事情,如果存在多个处理器还可以重复输出。
  • Formatter:格式化器,有些框架也叫Layout,就是格式化信息的,比如我们看到上面工工整整的时间,日志级别,就是我们定义好的格式,交给他处理。

正常打印一条日志,都是由日志记录器开始,日志记录器存在属性Handler处理器,处理器Handler存在属性Formatter。因此我们需要操作的对象就是Formatter

import logging  if __name__ == '__main__':  # Logger Handler Formatter 三者之间的关系,相互链接建立联系  formatter = logging.Formatter(logging.BASIC_FORMAT)  handler = logging.StreamHandler()  handler.setFormatter(formatter)  logging.getLogger().addHandler(handler)

因此我们如果要自定义处理器或者自定义格式化器,都是从上面的setFormatter和addHandler入手的。

如何自定义这些组件? 答案是继承,Python中我们无法实现接口,但是可以继承基类,只要是儿子,自然也就是处理器,或者格式化器。

class CustomFormatter(logging.Formatter):  # 重写父类的方法,再调用父类,相当于增强方法def format(self, record):   # 这里就可以处理记录record的了s = super().format(record)  return s

我们的基本思路就是拿到需要格式化的数据,%(asctime)s时间字符串,%(levelname)s等级字符串这些,拿到这些数据那就可以进行彩色处理了。

终端彩色显示

ANSI转义序列(ANSI escape sequences)是一种带内信号的转义序列标准,用于控制视频文本终端上的光标位置、颜色和其他选项。在文本中嵌入确定的字节序列,大部分以ESC转义字符和"["字符开始,终端会把这些字节序列解释为相应的指令,而不是普通的字符编码。

大体原理就是类似\r代表回到开头,\n代表换行这种,具有一定的转义含义的东西,在终端不同的转义含义就可以控制输出的字体颜色,背景颜色,字体加粗,划线等等。

基本格式为:

\033[XXXm

其中\033[以及后面的m都是固定的,只有XXX代表不同含义,分别由;分割,比如下面的例子

print("\033[31;9;3mHello Python\033[m")

其中31表示前景色(字体颜色)为红色,9表示划除线,3表示斜体

效果图
在这里插入图片描述

注意:并不是说第一个数字一定要控制颜色,也可以完全没有颜色控制的!

具体的ANSI转义表参考复杂正规版

简单的网上搜一下就好,就是说每个数字代表什么含义的码表,比如你想要粗体应该是数字1。

我们的目的是颜色,标准颜色的数字是30~37分别如下表示:

颜色前景色代码
黑色30
红色31
绿色32
黄色33
蓝色34
品红35
青色36
白色37
print("\033[31mINFO\033[m")  
print("\033[32mINFO\033[m")  
print("\033[33mINFO\033[m")  
print("\033[34mINFO\033[m")  
print("\033[35mINFO\033[m")  
print("\033[36mINFO\033[m")  
print("\033[37mINFO\033[m")

效果图
在这里插入图片描述

所以我们只需要获取到指定字符串然后包裹封装就可以了,问题是怎么获取呢?

完整实现

from enum import Enum
import logging# 枚举类用来记录颜色
class Color(Enum):  BLACK = 30  RED = 31  GREEN = 32  YELLOW = 33  BLUE = 34  CYAN = 36 WHITE = 37 DEFAULT = 39 # ANSI转义颜色包裹需要颜色显示的字符串
def color_text(text: str, color: Color) -> str:  return "\033[{}m{}\033[0m".format(str(color.value), text)# 自定义格式化器继承Formatter,在format格式化之前拿到需要变化的字段字符串,这里主要就是日志级别和记录器名称
class CustomFormatter(logging.Formatter):  def format(self, record):  if record.levelname == "INFO":  level_name_color = Color.GREEN  elif record.levelname == "ERROR":  level_name_color = Color.RED  elif record.levelname == "WARNING":  level_name_color = Color.YELLOW  else:  level_name_color = Color.DEFAULT  record.levelname = color_text(record.levelname, level_name_color)  record.name = color_text(record.name, Color.CYAN)  s = super().format(record)  return s# 设置自定义格式化器,这里封装一个方法用来获取日志记录器,正好在这里添加格式化器,控制台输出处理器Handler默认是StreamHandler
def getLogger(name: str = __name__):  logger = logging.getLogger(name)  handler = logging.StreamHandler()  handler.setLevel("DEBUG")  format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"  handler.setFormatter(CustomFormatter(fmt=format))  logger.addHandler(handler)  logger.propagate = 0  return logger

效果图
在这里插入图片描述

注意:这里需要配置记录器的日志级别,记录器的日志级别向下传递给处理器,所以其实处理器本质不设置日志级别也是可以的,由记录器传递。

上面还有个关键问题,为什么整体颜色还是红色?

答案是对于终端的输出分为stdout和stderr,而StreamHandler.stream输出流默认输出为stderr,因为我们还需要加一行关键的代码。

getLogger方法中添加

handler.stream = sys.stdout

最终效果图
在这里插入图片描述

Note:

  • 为了更接近SpringBoot效果,对格式化内容做了调整
  • 日志级别其实最高也就WARNING共7个字符,但是由于加了转义序列,实际长度并不是7,因此如果太小则会出现对不齐的情况,这里采用%(levelname)18s占位18个字符右对齐。

格式化标准:

format = "%(asctime)s - %(levelname)18s - [%(name)15s] - %(message)s"

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com