在测试阶段,我们经常会遇到这样的场景:需要对遗留系统进行功能验证,但代码中充斥着大量用于调试的print语句。直接删除这些语句可能会影响后续调试效率,而保留它们又会导致测试输出混乱,难以捕捉关键信息。此时,如何在不修改原有代码的前提下,将这些分散的print输出统一收集并结构化记录,就成为提高测试效率的关键挑战。
本文介绍的print函数重定向技术,正是为解决这一问题而生。通过临时替换 Python 内置的print函数,我们可以将所有输出自动导向专业的日志系统,实现以下优势:
print语句,避免引入新的代码风险logging模块,可以对输出进行级别分类、文件存储和格式化处理,便于后续分析在实际测试场景中,适用于以下情况:
下面是一个典型的测试场景应用示例:
import builtins
import logging
from functools import partial
import sys
def setup_logger(logger_name="print_logger", log_level=logging.INFO, log_file=None):
"""配置logger"""
logger = logging.getLogger(logger_name)
logger.setLevel(log_level)
# 确保没有重复的处理器
if not logger.handlers:
# 添加控制台处理器
console_handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# 添加文件处理器(如果指定了文件)
if log_file:
file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
def override_print(logger, sep=' ', end='\n', flush=False):
"""替换内置print函数,将输出发送到logger"""
original_print = builtins.print
def new_print(*args, sep=sep, end=end, file=sys.stdout, flush=flush):
# 如果指定了文件,则使用原始print
if file is not sys.stdout:
return original_print(*args, sep=sep, end=end, file=file, flush=flush)
# 构建消息并发送到logger
message = sep.join(map(str, args)) + end
logger.info(message.rstrip('\n'))
builtins.print = new_print
return original_print # 返回原始print,以便需要时恢复
def restore_print(original_print):
"""恢复原始print函数"""
builtins.print = original_print
# 使用示例
if __name__ == "__main__":
# 配置logger
logger = setup_logger(log_file="print.log")
# 备份原始print函数
original_print = builtins.print
# 替换print函数
override_print(logger)
# 现在所有print都会记录到日志
print("这是一条测试消息")
print("多个参数", "会被自动合并")
# 如果需要临时使用原始print
original_print("这是使用原始print输出的内容")
# 恢复原始print
restore_print(original_print)
print("现在print已恢复正常") 运行结果示例

通过灵活配置日志级别和输出目标,我们可以在不干扰系统正常运行的前提下,获取所需的调试信息。
#Python #Python日志