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

如何实现Python代码输出同时写入txt文件并在终端显示?

Python实现print同时输出到终端和文件的方法

问题原因

直接将sys.stdout赋值为文件对象会完全覆盖默认的终端输出流,所有print输出只会流向指定文件,无法在终端展示,直接关闭文件句柄还可能导致后续标准输出报错。
原始问题代码:

import sys
from librk2.auth import Auth
from librk2.exceptions import LibrkError
from librk2.cr.server import CrServer
from librk2.helpers.ip4finder import IP4Finder

try:
    auth = Auth('my program', interactive=True)
    server = IP4Finder(auth, "1.1.1.1")
    deviceid = CrServer(auth, (server.device_id))
except LibrkError as ex:
    print(ex.message)
    sys.exit(ex.code)

sys.stdout=open("test.txt","w")
print("Current Machine type: {0}".format(deviceid.os_type))
sys.stdout.close()

可选实现方案

方案1:自定义双输出流类(无依赖,最小改动原有代码)

自定义类同时持有终端原始输出流和日志文件流,写入操作同步发送到两个流,改动量最小:

import sys
from librk2.auth import Auth
from librk2.exceptions import LibrkError
from librk2.cr.server import CrServer
from librk2.helpers.ip4finder import IP4Finder

class DualStream:
    def __init__(self, *output_streams):
        self.streams = output_streams
    
    def write(self, content):
        for s in self.streams:
            s.write(content)
            s.flush() # 实时刷新缓存,避免输出延迟
    
    def flush(self):
        for s in self.streams:
            s.flush()

if __name__ == "__main__":
    try:
        auth = Auth('my program', interactive=True)
        server = IP4Finder(auth, "1.1.1.1")
        deviceid = CrServer(auth, (server.device_id))
    except LibrkError as ex:
        print(ex.message)
        sys.exit(ex.code)

    # 保存原始终端输出流
    origin_stdout = sys.stdout
    # 打开日志文件,指定utf-8编码避免乱码
    log_file = open("test.txt", "w", encoding="utf-8")
    # 替换标准输出为双路流
    sys.stdout = DualStream(origin_stdout, log_file)

    # 后续print会同时输出到终端和文件
    print("Current Machine type: {0}".format(deviceid.os_type))

    # 用完恢复原始输出流,关闭文件
    sys.stdout = origin_stdout
    log_file.close()

注意事项:

  • 打开文件时指定encoding="utf-8",避免Windows等系统下中文输出乱码
  • 每次写入后执行flush操作,避免缓存导致终端或文件内容不实时
  • 程序退出前必须恢复原始stdout、关闭文件句柄,防止资源泄漏

方案2:使用标准库logging(适合长期维护的日志场景)

如果后续需要扩展日志级别、时间戳、日志切割等能力,直接使用Python内置的logging模块更稳定,不需要手动维护流对象:

import logging
import sys
from librk2.auth import Auth
from librk2.exceptions import LibrkError
from librk2.cr.server import CrServer
from librk2.helpers.ip4finder import IP4Finder

# 配置日志同时输出到终端和文件
logging.basicConfig(
    level=logging.INFO,
    format="%(message)s", # 如需加时间、日志级别可修改格式,比如"%(asctime)s - %(levelname)s - %(message)s"
    handlers=[
        logging.FileHandler("test.txt", encoding="utf-8"),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger()

try:
    auth = Auth('my program', interactive=True)
    server = IP4Finder(auth, "1.1.1.1")
    deviceid = CrServer(auth, (server.device_id))
except LibrkError as ex:
    logger.error(ex.message)
    sys.exit(ex.code)

logger.info("Current Machine type: {0}".format(deviceid.os_type))

该方案无需手动处理流的关闭、恢复逻辑,模块会自动管理资源,扩展性更强。


内容的提问来源于stack exchange,提问作者Navdeep.D2

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:18:25