Windows下可靠重定向stdout和stderr到文件以避免输出不同步的方法
我太懂这种输出顺序乱掉的糟心感了!你提到用dir > a.txt 2>&1这类命令重定向时,stdout和stderr的输出顺序和控制台不一致——比如错误信息可能随机插在正常输出里,这本质是因为标准输出(stdout)默认是块缓冲的,而标准错误(stderr)是无缓冲的:控制台运行时系统会帮你同步显示,但重定向到文件时,缓冲机制的差异就会导致两个流的输出顺序混乱。
先确认下你复现问题的场景:运行这个Python命令后生成的out.txt确实会出现顺序错乱:py -c "for i in range(5, -1, -1): print(1/i)" > out.txt 2>&1
乱序的输出大概是这样:
Traceback (most recent call last):
0.2
0.25
0.3333333333333333
0.5
1.0
File ""...
给你几个不用修改程序本身的可靠解决办法:
针对Python脚本的专属快速方案:
Python的py/python命令自带-u参数,它会强制stdout和stderr都使用无缓冲模式,让两个流的输出顺序完全对齐控制台的显示效果。把你的命令改成这样就行:py -u -c "for i in range(5, -1, -1): print(1/i)" > out.txt 2>&1通用方案(适用于所有Windows程序):
改用PowerShell的合并重定向+管道输出——PowerShell会先把stdout和stderr合并成一个统一的流,再写入文件,从根源上避免顺序混乱。命令格式如下:py -c "for i in range(5, -1, -1): print(1/i)" *>&1 | Out-File out.txt
要是你需要UTF-8编码的文件,再加个编码参数就好:Out-File out.txt -Encoding utf8CMD环境下的通用技巧:
如果你习惯用CMD,可以先让程序的两个流都输出到控制台,再用more命令(它会强制同步两个流)把内容写入文件,注意要转义引号:cmd /c "py -c \"for i in range(5, -1, -1): print(1/i)\" 2>&1 | more > out.txt"
用上面的方法再跑测试命令,out.txt里的错误信息和正常输出顺序就会和你直接在命令行运行看到的完全一致——错误栈会出现在最后,不会再乱序了。
备注:内容来源于stack exchange,提问作者FamousSnake

