直接传入sys.stdout与通过变量传入为何改变print输出顺序?
为什么直接传sys.stdout和先赋值给变量再传,会导致print输出捕获行为不同?
我尝试捕获函数中的print输出以便后续使用,先写出了如下代码:
import io import sys from contextlib import redirect_stdout f = io.StringIO() def hello(): print("From function", file=sys.stdout) with redirect_stdout(f): hello() print("Message from main") print(f.getvalue())
输出符合预期:
Message from main From function
但我发现,如果把sys.stdout赋值给变量后再传入print函数,行为会发生变化,代码如下:
import io import sys from contextlib import redirect_stdout filedest = sys.stdout f = io.StringIO() def hello(): print("From function", file=filedest) with redirect_stdout(f): hello() print("Message from main") print(f.getvalue())
输出变为:
From function Message from main
可见输出顺序已反转,疑惑为何直接传入sys.stdout与通过变量传入会导致这种差异?
原因解析
核心在于redirect_stdout的工作机制:它只是临时替换sys.stdout这个全局变量的指向,并不会修改已经创建好的文件对象本身。
第一种场景:
hello函数里的print指定file=sys.stdout,在with代码块执行时,sys.stdout已经被替换成了f(io.StringIO对象),所以print的内容会写入f,被成功捕获。后续主程序的print("Message from main")是在with块结束后执行,此时sys.stdout恢复为原始的标准输出(终端),所以先输出这条内容,再打印f中存储的捕获内容。第二种场景:
filedest = sys.stdout是在with块执行前完成赋值的,此时filedest直接指向原始的标准输出流(比如终端)。哪怕后续redirect_stdout替换了sys.stdout的指向,filedest的指向不会改变,所以hello函数里的print会直接把内容输出到终端,而不是被f捕获。主程序的print("Message from main")随后执行,所以输出顺序就反过来了。
内容的提问来源于stack exchange,提问作者Gul
相关产品推荐
相关产品推荐

