重定向sys.stdout需开启行缓冲、手动关闭文件并处理编码;推荐用contextlib.redirect_stdout上下文管理器确保安全还原。

sys.stdout重定向后print输出不生效
直接赋值 sys.stdout = open('out.txt', 'w') 看似简单,但 print 会卡住或内容丢失——因为文件对象默认行缓冲关闭,且没处理 flush 和 close。Python 的 print() 在重定向后仍依赖 sys.stdout.flush() 触发写入,而你手动打开的文件没被自动管理生命周期。
- 必须用
sys.stdout = open('out.txt', 'w', buffering=1)开启行缓冲(buffering=1),否则换行也不刷出 - 重定向期间所有 print、help()、traceback 都进文件,但程序退出前得手动
sys.stdout.close(),否则末尾内容可能丢 - 别在重定向中途调用
input()—— 它也读sys.stdin,但输出流已指向文件,用户看不到提示
想临时捕获输出又不影响后续终端显示
硬改 sys.stdout 是全局污染,一不小心就让日志、第三方库或 REPL 失效。真正安全的做法是用上下文管理器局部接管,比如 contextlib.redirect_stdout。
- 用法:
from contextlib import redirect_stdout with open('log.txt', 'w') as f: with redirect_stdout(f): print('这行进文件') # 其他函数调用里的 print 也进文件 print('这行还在终端') - 它底层替换了
sys.stdout并确保退出时自动还原,不怕异常中断导致终端“失声” - 注意:不能嵌套多个
redirect_stdout到不同文件,内层会覆盖外层;如需分段记录,改用io.StringIO先存内存再写盘
重定向 subprocess 输出时 stdout=PIPE 不等于终端输出
很多人想把 subprocess.run(['ls', '-l'], ...) 的结果存文件,却误以为设 stdout=subprocess.PIPE 就能顺手重定向到磁盘——其实 PIPE 只是把输出抓进 Python 字符串,和文件无关。
- 正确做法是直接传文件对象:
with open('cmd_out.txt', 'w') as f: subprocess.run(['ls', '-l'], stdout=f, stderr=subprocess.STDOUT) -
stderr=subprocess.STDOUT很关键:否则错误信息仍打屏,尤其调试时容易漏看 - 如果命令输出超大(如
tar -czf日志),避免用capture_output=True+.stdout.decode(),会吃光内存;优先用文件流直写
Windows 下中文重定向乱码或报错
在 CMD 或 PowerShell 里跑 Python 脚本,open('out.txt', 'w') 默认用系统编码(通常是 gbk),但脚本里 print 的字符串是 Unicode,直接写会触发 UnicodeEncodeError。
- 显式指定 encoding:
open('out.txt', 'w', encoding='utf-8'),并在终端用chcp 65001切到 UTF-8 模式(否则记事本打不开) - 更稳妥的是用
locale.getpreferredencoding()动态取终端编码,但 Windows 上它常返回 'cp936',和实际 cmd 的 cp437 不一致——不如统一用 utf-8 + 改终端 - VS Code 终端默认 utf-8,但它的 Python 扩展有时会绕过你的 encoding 设置,此时加
sys.stdout.reconfigure(encoding='utf-8')(Python 3.7+)强制生效
重定向不是“设个变量就完事”,核心在于缓冲控制、生命周期管理和编码对齐。最常被跳过的其实是 close 和 flush —— 一关终端,最后一行就没了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











