Flask日志写入文件时移除Bash颜色(ANSI字符)的实现方案问询
Flask日志写入文件时移除Bash颜色(ANSI字符)的实现方案问询
嘿,我太懂你的需求了——控制台日志带颜色看着清爽又好区分级别,但是写入文件的日志里混着一堆ANSI颜色控制字符,打开文件全是乱码似的符号,读起来简直遭罪对吧?
你已经在写自定义的CustomFormatter了,这个方向完全踩对了!我给你补全具体的实现思路和代码,刚好能无缝衔接你现在的配置:
首先核心思路很明确:要么让自定义Formatter自动识别输出目标(控制台/文件)切换模式,要么给控制台和文件分别配置两个Formatter——一个加颜色,一个清掉所有ANSI字符。我给你写的是第一种自动适配的方案,用起来更省心:
from logging.config import dictConfig from logging import Formatter import re from flask import has_request_context, request # 匹配所有ANSI控制字符的正则 ANSI_ESCAPE_PATTERN = re.compile(r'\x1B(?:[@-Z\\-_]|\[.*?[a-zA-Z])') class CustomFormatter(Formatter): # 控制台用的颜色映射表 COLORS = { 'DEBUG': '\033[94m', # 蓝色 'INFO': '\033[92m', # 绿色 'WARNING': '\033[93m', # 黄色 'ERROR': '\033[91m', # 红色 'CRITICAL': '\033[95m', # 洋红色 'RESET': '\033[0m' # 重置颜色 } def format(self, record): # 先调用父类拿到原始格式化后的日志消息 message = super().format(record) # 如果你需要给日志加请求上下文信息(比如请求方法、路径),就在这里加 if has_request_context(): message = f"{request.method} {request.path} - {message}" # 自动判断输出目标:控制台的流是tty设备,文件流不是 is_console_output = hasattr(record, 'handler') and hasattr(record.handler.stream, 'isatty') and record.handler.stream.isatty() if is_console_output: # 控制台输出:给不同级别加对应颜色 level_color = self.COLORS.get(record.levelname, self.COLORS['RESET']) message = f"{level_color}{message}{self.COLORS['RESET']}" else: # 文件输出:彻底清掉所有ANSI控制字符 message = ANSI_ESCAPE_PATTERN.sub('', message) return message def configure_logging(): """ 配置日志系统 """ dictConfig({ 'version': 1, 'formatters': { 'common': { 'format': '%(asctime)s - %(levelname)s - %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S', '()': 'utils.log_utils.CustomFormatter' }, 'error': { 'format': '%(asctime)s - %(levelname)s - %(module)s - %(lineno)d - %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S', '()': 'utils.log_utils.CustomFormatter' } }, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'level': 'DEBUG', 'formatter': 'common' }, 'file': { 'class': 'logging.FileHandler', 'filename': 'app.log', 'level': 'INFO', 'formatter': 'common', 'encoding': 'utf-8' }, 'error_file': { 'class': 'logging.FileHandler', 'filename': 'errors.log', 'level': 'ERROR', 'formatter': 'error', 'encoding': 'utf-8' } }, 'root': { 'level': 'DEBUG', 'handlers': ['console', 'file', 'error_file'] } })
给你划几个关键细节:
- 那个正则表达式能匹配所有常见的ANSI控制序列,不管是颜色、光标移动还是其他控制字符,都能一次性清干净
- 通过
record.handler.stream.isatty()判断是不是控制台输出,完全自动切换,不用你手动配置区分 - 你之前配置的
errorformatter也用了CustomFormatter,这样错误日志也会自动适配控制台彩色、文件无干扰的模式,完美契合你的需求
要是你不想自动判断,也可以直接拆分两个Formatter:一个ColoredFormatter专门给控制台加颜色,一个PlainFormatter专门给文件清ANSI字符,配置的时候给对应Handler用就行,灵活性拉满~
备注:内容来源于stack exchange,提问作者lolozen
相关产品推荐
相关产品推荐

