最可靠方法是命令行重定向:python train.py > log.txt 覆盖写入,>> 追加,> log.txt 2>&1 合并错误(无空格);launch.json 和 scrollback 设置无法保存输出;logging.basicconfig 可主动落盘,需注意路径和 filemode。

终端命令运行时直接加 >> 或 2>&1 最可靠
VSCode 终端本身不保存输出,关掉就丢——这不是 bug,是设计。唯一零依赖、跨平台、立刻生效的办法,就是在运行命令时手动重定向。
-
python train.py > log.txt:覆盖写入标准输出,文件不存在会自动创建 -
python train.py >> log.txt:追加写入,适合多次运行累积日志 -
python train.py > log.txt 2>&1:把错误也合并进去,2>&1必须紧贴>,中间不能有空格(PowerShell 和 bash 都认这个写法) - 路径是相对的,基于你当前终端所在目录(通常是项目根目录),不是 VSCode 窗口路径
- 别用
cat log.txt查看——改用tail -f log.txt实时追踪新增内容
为什么改 launch.json 的 console 字段没用
很多人以为把 launch.json 里 "console": "integratedTerminal" 换成 "externalTerminal" 或调大 terminal.integrated.scrollback 就能“保存输出”,其实不能。这些设置只影响输出显示位置或缓冲行数,不改变输出是否落盘。
-
scrollback默认是 1000 行,调到 5000 或 10000 可防翻页丢失,但内存占用会上升,尤其 WSL 下明显卡顿 - 调试控制台(Debug Console)和集成终端(Integrated Terminal)是两套独立输出通道:
print()走终端,logging.info()默认走调试控制台——它们互不共享缓冲区 - 就算开了自动保存(
files.autoSave: "afterDelay"),也只保存编辑器里的源码文件,跟运行输出无关
logging.basicConfig 在脚本内主动落盘
如果需要带时间戳、分级(INFO/WARN/ERROR)、或区分不同模块的日志,终端重定向就不够用了。这时候得在代码里主动接管输出流向。
-
import logging; logging.basicConfig(filename="run.log", level=logging.INFO, format="%(asctime)s - %(message)s"):之后所有logging.info("start")都自动写进文件 -
print()还是只打到终端,不会进日志;必须统一用logging.xxx() - 文件路径是相对于脚本运行时的当前工作目录,不是脚本所在目录;想绝对路径就用
os.path.dirname(__file__)拼接 - 如果日志文件被其他进程占用(比如正用记事本打开),
basicConfig默认会静默失败,建议加filemode="a"显式声明追加模式
用 subprocess.run 在 Python 里捕获并保存输出
适合封装成自动化流程:比如跑完模型训练,自动存日志、发邮件、触发下一步。它绕过终端,直接从子进程管道读取原始输出。
result = subprocess.run(["python", "train.py"], capture_output=True, text=True)with open("log.txt", "w") as f: f.write(result.stdout); f.write(result.stderr)- 等价于
stdout=subprocess.PIPE, stderr=subprocess.PIPE;text=True避免字节串处理 - 真正容易被忽略的是:
print()和logging默认行为仍取决于调用上下文——子进程里写的日志,不会自动继承父进程的basicConfig
实际操作中,最常被漏掉的是路径语义混淆:终端重定向的路径基于 pwd,而 logging.basicConfig 的路径基于 os.getcwd(),两者可能不同;还有 2>&1 中间多一个空格就会失效,这种细节一错就静默失败。











