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

如何在Python中实现类似Linux tee命令的同时输出与日志记录?

Python实现tee功能递归错误的原因及解决方法

错误原因

  • 大概率是你在实现时替换了系统默认的sys.stdout,同时在自定义的输出逻辑里直接调用了print()——而print()默认会使用被替换后的sys.stdout,导致无限递归调用,最终触发RecursionError。
  • 举个典型的错误示例(你可能写了类似代码):
import sys

class Tee:
    def __init__(self, filename):
        self.file = open(filename, 'a')
        sys.stdout = self

    def write(self, msg):
        self.file.write(msg)
        print(msg)  # 这里调用print会再次触发write,无限递归

tee = Tee('log.txt')
print('test')

解决方法

方法1:保留原始stdout,避免递归调用

不要用print(),直接调用保存的原始sys.stdout的write方法,彻底切断递归链:

import sys

class Tee:
    def __init__(self, filename):
        self.file = open(filename, 'a', encoding='utf-8')
        self.original_stdout = sys.stdout
        sys.stdout = self

    def write(self, msg):
        # 写入日志文件
        self.file.write(msg)
        # 输出到控制台(用原始stdout,不会触发递归)
        self.original_stdout.write(msg)
        # 强制刷新缓冲区,避免输出延迟
        self.original_stdout.flush()
        self.file.flush()

    def flush(self):
        # 必须实现flush方法,否则部分场景下输出会卡住
        self.original_stdout.flush()
        self.file.flush()

# 使用示例
tee = Tee('log.txt')
print('这条信息会同时输出到控制台和日志文件')
# 用完记得恢复原始stdout,避免影响后续代码
sys.stdout = tee.original_stdout
tee.file.close()

方法2:直接写专用输出函数(简单无坑)

如果不需要全局替换所有print,直接写个独立函数更省心,完全不会有递归问题:

def tee_print(msg, log_file='log.txt'):
    # 输出到控制台
    print(msg)
    # 写入日志文件
    with open(log_file, 'a', encoding='utf-8') as f:
        f.write(f'{msg}\n')

# 使用示例
tee_print('这条信息同时出现在控制台和日志')
tee_print('另一条测试信息', log_file='my_log.txt')

方法3:用上下文管理器(优雅且安全)

用上下文管理器包装功能,自动处理stdout的恢复和文件关闭,避免遗忘清理:

import sys
from contextlib import contextmanager

@contextmanager
def tee(filename):
    original_stdout = sys.stdout
    log_file = open(filename, 'a', encoding='utf-8')
    
    class TeeStream:
        def write(self, msg):
            log_file.write(msg)
            original_stdout.write(msg)
            original_stdout.flush()
            log_file.flush()
        
        def flush(self):
            original_stdout.flush()
            log_file.flush()
    
    sys.stdout = TeeStream()
    try:
        yield
    finally:
        # 退出上下文时自动恢复环境
        sys.stdout = original_stdout
        log_file.close()

# 使用示例
with tee('log.txt'):
    print('进入上下文,所有print都会同时写文件')
    print('多条信息都能被捕获')
# 退出后,print恢复正常输出到控制台
print('这条只会显示在控制台')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 04:32:11