尽管配置了 `colors=False`,structlog的 ConsoleRenderer仍然把带有颜色控制码的堆栈跟踪信息写入到文件中

编程语言 2026-07-11

我正在将日志输出到两个目标:控制台和日志文件,正如structlog文档在 [本节] 中所建议的最终方案所示:

def configure_logging(verbosity: int, config: LogOptions):
    console_log_level = max(logging.DEBUG, logging.WARNING - verbosity * 10)
    assert logging.DEBUG <= console_log_level <= logging.WARNING
    file_log_level = min(logging.INFO, console_log_level)
    assert logging.DEBUG <= file_log_level <= logging.INFO
    root_log_level = min(console_log_level, file_log_level)

    timestamper = structlog.processors.TimeStamper(fmt="iso")
    # these are applied to log records emitted via the stdlib's logging facilities
    foreign_records_processors = (
        structlog.stdlib.add_log_level,
        structlog.stdlib.ExtraAdder(),
        timestamper,
    )

    logging.config.dictConfig(
        {
            "version": 1,
            "disable_existing_loggers": False,
            "formatters": {
                "logfile": {
                    "()": structlog.stdlib.ProcessorFormatter,
                    "foreign_pre_chain": foreign_records_processors,
                    "processors": (
                        structlog.stdlib.ProcessorFormatter.remove_processors_meta,
                        structlog.dev.ConsoleRenderer(colors=False),
                    ),
                },
                "console": {
                    "()": structlog.stdlib.ProcessorFormatter,
                    "foreign_pre_chain": foreign_records_processors,
                    "processors": (
                        structlog.stdlib.ProcessorFormatter.remove_processors_meta,
                        structlog.dev.ConsoleRenderer(
                            colors=True,
                            exception_formatter=structlog.dev.plain_traceback,
                        ),
                    ),
                },
            },
            "handlers": {
                "console": {
                    "class": "logging.StreamHandler",
                    "formatter": "console",
                    "level": console_log_level,
                },
                "file": {
                    "class": "logging.handlers.WatchedFileHandler",
                    "filename": config["file"],
                    "formatter": "logfile",
                    "level": file_log_level,
                },
            },
            "loggers": {
                "": {
                    "handlers": ("console", "file"),
                    "level": root_log_level,
                    "propagate": True,
                }
            },
        }
    )

    structlog.configure(
        cache_logger_on_first_use=True,
        logger_factory=structlog.stdlib.LoggerFactory(),
        processors=(
            structlog.stdlib.add_log_level,
            timestamper,
            structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
        ),
        wrapper_class=structlog.stdlib.BoundLogger,
    )

然而,被写入日志文件的回溯信息包含转义序列(例如 ESC[32m)。

在我把这当成一个错误之前,我在想自己是否在这个设置中遗漏了什么。

解决方案

正如我起初没有意识到,只有由Rich库格式化的异常追踪才会受此现象影响,因此我认定需要一个 exception_formatter——它并未直接被 structlog 当前的类型注解所支持——这是必需的:

…
    "formatters": {
        "logfile": {
            "()": structlog.stdlib.ProcessorFormatter,
            "foreign_pre_chain": foreign_records_processors,
            "processors": (
                structlog.stdlib.ProcessorFormatter.remove_processors_meta,
                structlog.dev.ConsoleRenderer(
                    colors=False,
                    exception_formatter=structlog.dev.RichTracebackFormatter(
                        color_system=None
                    ),
                ),
            ),
        },
…
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章