代码执行日志记录


忘了在哪个开源项目里看到了一个执行日志系统。它会在每次运行时备份代码。对于我这种随时会忘掉实验结果和实验设置的人来说,这种东西应该会很有用……吧。凭印象和自己的喜好复现了一下,具体如下。

首先,项目应该保持如下的结构。code路径下存放所有的代码,任何数据和中间运行结果都应该放在这里。log目录下存放所有的日志记录。其它的目录根据自己喜好设置。
代码路径

在code/util路径下,新建一个code_logger.py。粘贴如下内容。该日志模块下集成了代码备份、参数保存、日志输出与保存的功能。

import os
from datetime import datetime
import shutil
import json
import logging


class CodeLogger:
    def __init__(self, comment=None, args=None):
        self.run_time = datetime.now()
        self.time_fmt = "%Y-%m-%d-%H-%M-%S"
        # self.time_fmt = "%Y%m%d%H%M%S"
        self.comment = comment
        self.log_dir = self.run_time.strftime(self.time_fmt)
        if comment is not None:
            self.log_dir = f"{self.log_dir}-{comment}"
        self.log_dir = os.path.join("../log", self.log_dir)
        self.args = args

        # create log dir if not exists
        if not os.path.exists(self.log_dir):
            os.mkdir(self.log_dir)

        # back up codes
        shutil.copytree("../code/", os.path.join(self.log_dir, "code/"))
        if self.args is not None:
            self.save_args(args)
        self.logger = self.init_logger()

    def save_args(self, args):
        with open(os.path.join(self.log_dir, "args.json"), "w") as f:
            json.dump(args.__dict__, f)

    def init_logger(self):
        logger = logging.getLogger(self.comment)
        logger.setLevel(logging.INFO)
        log_format = logging.Formatter(
            "%(asctime)s %(levelname)-8s %(message)s")
        filename = os.path.join(self.log_dir, "run.log")
        log_handler = logging.FileHandler(filename, mode="w")
        log_handler.setLevel(logging.INFO)
        log_handler.setFormatter(log_format)
        logger.addHandler(log_handler)
        console_logger = logging.StreamHandler()
        console_logger.setLevel(logging.INFO)
        console_logger.setFormatter(log_format)
        logger.addHandler(console_logger)
        return logger

在使用该模块时,需要先import该模块。演示如下:

from util.models import get_architecture
from util.code_logger import CodeLogger
import argparse


parser = argparse.ArgumentParser()
parser.add_argument("--model", type=str, default="resnet")
parser.add_argument("--dataset", type=str, default="cifar10")
parser.add_argument("--epochs", type=int, default=150)
parser.add_argument("--batch_size", type=int, default=256)
parser.add_argument("--lr", type=float, default=0.01)
parser.add_argument("--verbose", action="store_true")
args = parser.parse_args()

model_name = args.model
dataset = args.dataset
epochs = args.epochs
batch_size = args.batch_size
lr = args.lr
verbose = args.verbose

cl = CodeLogger(comment=f"train model {model_name}_{dataset}", args=args)
''' 上面是日志模块初始化,初始化会做三件事:
1. 在log文件夹下新建一个文件夹,文件夹名称为“当前时间-comment内容”。
2. 把code路径下所有文件保存到新建的文件夹中
3. 把运行参数args存放到新建文件夹的args.json中
'''
cl.logger.info(f"test output") # 控制台输出,同时会把输出内容保存到新建文件夹下的run.log中

如果再发生没有记录实验结果,或者忘掉实验设置时,就可以通过查找log目录下的代码备份或者参数备份来一键找回了。


文章作者: wangxh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 wangxh !
  目录