为何with语句内print代码无输出?Python stdout重定向问题排查
问题原因分析
核心问题出在两点:
- 使用
redirect_stdout后,所有print的输出会被完全重定向到fake_std_out这个内存流对象里,包括你在重定向上下文里写的print(data)——这些内容全存在内存里,根本不会输出到控制台,只有上下文外的print("THE END")能正常显示。 - 你的实际需求是复制stdout输出(既要在控制台看到内容,又要捕获输出),但当前代码用的是完全重定向,直接改了stdout的输出路径,自然看不到控制台输出。
解决方案
如果要同时实现控制台输出和内容捕获,可以自定义一个类似tee的逻辑,让输出同时写到控制台和内存流:
import sys from io import StringIO class TeeStringIO(StringIO): def write(self, s): # 同时输出到控制台和内存流 sys.stdout.write(s) super().write(s) def run_solver(): print("solver is running") with TeeStringIO() as fake_std_out: original_stdout = sys.stdout sys.stdout = fake_std_out try: print("BLAH") run_solver() data = fake_std_out.getvalue() print(data) finally: # 恢复原本的stdout sys.stdout = original_stdout print("THE END")
也可以用上下文管理器封装,让代码更简洁:
import sys from io import StringIO from contextlib import contextmanager @contextmanager def tee_stdout(): fake_std_out = StringIO() original_stdout = sys.stdout class Tee: def write(self, s): original_stdout.write(s) fake_std_out.write(s) sys.stdout = Tee() try: yield fake_std_out finally: sys.stdout = original_stdout fake_std_out.close() def run_solver(): print("solver is running") with tee_stdout() as fake_std_out: print("BLAH") run_solver() data = fake_std_out.getvalue() print(data) print("THE END")
运行后控制台会输出:
BLAH solver is running BLAH solver is running THE END
同时你也能通过data变量获取到捕获的输出内容。
补充:仅捕获输出不显示控制台的修正
如果只是想捕获输出但不需要控制台显示,只需把print(data)移到重定向上下文外面即可:
from contextlib import redirect_stdout import io def run_solver(): print("solver is running") with io.StringIO() as fake_std_out: with redirect_stdout(fake_std_out): print("BLAH") run_solver() # 离开重定向上下文后,stdout恢复正常,再打印捕获内容 data = fake_std_out.getvalue() print(data) print("THE END")
此时控制台输出:
BLAH solver is running THE END
内容的提问来源于stack exchange,提问作者Toothpick Anemone
相关产品推荐
相关产品推荐

