日志应写入带实验标识的独立子目录,用timedrotatingfilehandler按天轮转;主logger设info级并规范格式,框架logger单独设warning;多进程下各rank写独立文件;数值指标通过extra参数或tab分隔结构化记录。

训练日志该往哪写:文件路径和轮转策略不能硬编码
直接用 logging.basicConfig(filename="train.log") 看似省事,但实际跑多次实验时会覆盖旧日志,或者因路径不存在而静默失败。更糟的是,单个大日志文件会让分析变慢,也难按天/按实验拆分。
实操建议:
- 用
os.path.join拼接日志目录,确保路径可写;训练前先os.makedirs(log_dir, exist_ok=True) - 优先用
RotatingFileHandler或TimedRotatingFileHandler,比如每天一个文件:TimedRotatingFileHandler(filename, when="D", interval=1, backupCount=7) - 别把日志写进项目源码目录(如
./src/logs),统一放到./logs/<code>experiment_name这类带标识的子目录下
log level 和 format 怎么设才不丢关键信息
训练中常需要区分“模型收敛了”这类业务信息和“loss nan”这种异常信号。设成 INFO 会漏掉警告,设成 DEBUG 又塞满梯度形状等无用细节。
实操建议:
- 主 logger 设为
INFO,对torch或tensorflow等框架 logger 单独设为WARNING,避免被它们的调试日志淹没 - format 至少包含时间、level、模块名和消息:
"%(asctime)s | %(levelname)-8s | %(name)s | %(message)s" - 在每个 epoch 开始打
logger.info(f"Epoch {epoch} start"),结束打logger.info(f"Epoch {epoch} done, val_acc={acc:.4f}"),别只靠 print
多进程训练(DDP)下日志为什么乱序或缺失
用 torch.distributed.launch 或 accelerate 启动多卡训练时,所有进程默认往同一个文件写,结果日志交错、甚至损坏。有的进程还因为权限或缓冲问题根本没落盘。
实操建议:
- 每个 rank 写独立文件,比如
f"train_rank{rank}.log",而不是共用一个train.log - 禁用 buffering:
FileHandler(..., delay=False, encoding="utf-8"),并加logger.handlers[0].setLevel(logging.INFO)显式控制 - 如果只关心 rank 0 的日志(比如指标汇总),让其他 rank 的 handler 不生效:
if rank != 0: logger.disabled = True
怎么把 loss、lr、GPU 显存这些数值也记进日志文件
纯文本日志里混着数字很难后续解析,但又不能每行都写 JSON——可读性太差。直接 print 数值再 log,容易和普通消息混淆,也不方便对齐时间戳。
实操建议:
- 用结构化字段传入
logger.info("train_step", extra={"loss": loss.item(), "lr": lr, "gpu_mem": gpu_mem}),配合自定义 formatter 提取并格式化输出 - 更轻量的做法:固定字段名 + tab 分隔,比如
logger.info(f"step\t{step}\tloss\t{loss:.6f}\tlr\t{lr:.6f}"),之后用 pandas 读取时指定sep="\t" - 避免在循环里频繁调用
logger.info记录每个 step,每 10–50 步合并一次再 log,减少 I/O 压力
日志不是越全越好,而是要能快速定位“这次训练哪里开始崩的”。时间戳对齐、rank 隔离、数值可提取,这三点没做到,后面查问题就得靠猜。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











