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

如何使用Python logger将控制台所有内容(含unittest结果)写入日志文件

问题根因
  • unittest框架的测试运行结果(用例失败/错误提示、运行统计、堆栈信息)默认直接输出到标准输出/标准错误流,不会经过Python logging模块,所以你配置的logging文件handler无法捕获这部分内容
  • 未处理的全局异常默认也会直接打印到标准错误流,同样不会触发logging的记录逻辑
  • 你当前的logging配置放在测试类的类属性定义区,虽然能生效,但后续重复加载容易出现日志重复打印的问题,建议移到全局初始化位置
兼容Windows/Linux的实现方案

该方案会将所有控制台输出全量同步写入日志文件,同时满足unittest测试结果记录、未处理异常记录的需求。

import sys
import logging
import unittest
import datetime
import pathlib

# 流重定向类,将标准输出/错误内容转写入logging
class StreamToLogger:
    def __init__(self, logger, log_level=logging.INFO):
        self.logger = logger
        self.log_level = log_level
        self.linebuf = ''

    def write(self, buf):
        for line in buf.rstrip().splitlines():
            self.logger.log(self.log_level, line.rstrip())

    def flush(self):
        pass

# 全局初始化logging配置
logFormatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
rootLogger = logging.getLogger()
rootLogger.setLevel(logging.DEBUG)

# 日志文件handler配置
logfile_name = datetime.datetime.now().strftime(pathlib.PurePath(__file__).stem + '_%H_%M_%d_%m_%Y')
fileHandler = logging.FileHandler(f"{logfile_name}.log", encoding='utf-8')
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)

# 控制台输出handler配置,直接输出到原始stderr避免重定向循环
consoleHandler = logging.StreamHandler(sys.__stderr__)
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)

# 重定向标准输出、标准错误到logging
stdout_logger = logging.getLogger('STDOUT')
sys.stdout = StreamToLogger(stdout_logger, logging.INFO)
stderr_logger = logging.getLogger('STDERR')
sys.stderr = StreamToLogger(stderr_logger, logging.ERROR)

# 未处理异常捕获hook
def custom_excepthook(exc_type, exc_value, exc_traceback):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    rootLogger.critical("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
sys.excepthook = custom_excepthook

# 测试用例
class TestClass(unittest.TestCase):
    def test_logging(self):
        self.fail("Why is this not being logged into the log file?")

if __name__ == '__main__':
    unittest.main()
关键说明
  • 所有逻辑均使用Python标准库实现,无系统专属依赖,天然兼容Windows、Linux/Unix环境
  • 日志文件默认使用utf-8编码,避免Windows系统下的中文乱码问题
  • 备份了原始系统流作为控制台输出的目标,不会出现重定向后循环写入日志的问题

内容的提问来源于stack exchange,提问作者usustarr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 03:18:04