如何在Python中实时显示print输出并捕获所有历史print内容
问题:同时实时显示Python函数的print输出并捕获历史内容
当前使用装饰器捕获函数内的所有print输出及错误,但只能在函数执行完成后获取内容,无法实时看到print的输出效果。原代码如下:
import io import sys import time import traceback def return_std(func): def wrapper(*args, **kwargs): old_stdout = sys.stdout sys.stdout = buffer = io.StringIO() try: func(*args, **kwargs) except: print(traceback.format_exc()) finally: sys.stdout = old_stdout body = buffer.getvalue() buffer.close() return body return wrapper @return_std def some_useful_function(): print('so this line is executed at ' + time.strftime('%X')) time.sleep(5) print('program execute at ' + time.strftime('%X')) std_of_some_useful_function = some_useful_function() print(std_of_some_useful_function) print('but we can not know if it succeeded or failed before ' + time.strftime('%X'))
原输出效果:
program execute at 11:11:11 so this line is executed at 11:11:11 but we can not know if it succeeded or failed before 11:11:16
需求:修改装饰器,让函数内的print内容实时显示(和原生print效果一致),同时在函数执行完成后能获取所有历史输出内容。
解决方案:自定义双输出流类
核心思路是实现一个同时向原始标准输出和内存缓冲区写入内容的类,替换原来的单缓冲区StringIO。这样每次print时,内容会立刻显示到控制台,同时被记录下来供后续获取。
修改后的完整代码:
import io import sys import time import traceback class DupOutput: def __init__(self, original_stdout): self.original_stdout = original_stdout self.buffer = io.StringIO() def write(self, data): # 同时写入原始输出和缓冲区 self.original_stdout.write(data) self.buffer.write(data) # 强制刷新输出,确保实时显示 self.original_stdout.flush() def flush(self): # 实现flush方法,避免某些场景下的输出延迟 self.original_stdout.flush() self.buffer.flush() def getvalue(self): return self.buffer.getvalue() def close(self): self.buffer.close() def return_std(func): def wrapper(*args, **kwargs): old_stdout = sys.stdout # 初始化双输出流,同时指向原始stdout和缓冲区 sys.stdout = dup_output = DupOutput(old_stdout) try: func(*args, **kwargs) except Exception: # 捕获异常时,将错误信息同时输出和写入缓冲区 err_msg = traceback.format_exc() dup_output.write(err_msg) finally: sys.stdout = old_stdout body = dup_output.getvalue() dup_output.close() return body return wrapper @return_std def some_useful_function(): print('so this line is executed at ' + time.strftime('%X')) time.sleep(5) print('program execute at ' + time.strftime('%X')) std_of_some_useful_function = some_useful_function() print("=== 捕获的历史输出 ===") print(std_of_some_useful_function) print('now we can know execution status in real time and get all outputs at ' + time.strftime('%X'))
代码说明
DupOutput类:
- 初始化时保存原始的stdout和创建内存缓冲区
- 重写
write方法,每次写入数据时同时发送到原始输出和缓冲区,并且强制刷新原始输出确保实时显示 - 实现
flush方法,兼容标准输出的刷新逻辑 - 提供
getvalue和close方法,和StringIO的接口保持一致,方便替换使用
修改后的return_std装饰器:
- 将原来的io.StringIO替换为DupOutput实例,同时关联原始stdout
- 异常处理部分,将错误信息通过dup_output.write写入,确保错误信息也能实时显示并被捕获
- 最后恢复原始stdout,返回缓冲区的所有内容
运行效果
执行代码后,控制台会立刻显示so this line is executed at 11:11:11(不需要等待sleep结束),5秒后函数执行完成,后续会打印捕获的历史输出,最终输出如下:
program execute at 11:11:11 so this line is executed at 11:11:11 === 捕获的历史输出 === so this line is executed at 11:11:11 now we can know execution status in real time and get all outputs at 11:11:16
内容的提问来源于stack exchange,提问作者Dacian Peng
相关产品推荐
相关产品推荐

