You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()判断是不是控制台输出,完全自动切换,不用你手动配置区分
  • 你之前配置的error formatter也用了CustomFormatter,这样错误日志也会自动适配控制台彩色、文件无干扰的模式,完美契合你的需求

要是你不想自动判断,也可以直接拆分两个Formatter:一个ColoredFormatter专门给控制台加颜色,一个PlainFormatter专门给文件清ANSI字符,配置的时候给对应Handler用就行,灵活性拉满~

备注:内容来源于stack exchange,提问作者lolozen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 13:34:52