如何优雅地加载args命令行参数
参考资料:
使用Linux写一个python脚本,不可缺少的常客的就是argparse,这个小东西能够高效地解析命令行参数。但是一个经常的情景是命令行参数繁多,如果每次都在python XX.py后面接上一大堆参数,不仅不好看,而且容易出错。今天在EveryDream这个代码仓库看到一个非常优雅的方式,可以作为之后解析命令行参数的准绳!
argparser = argparse.ArgumentParser(description="EveryDream2 Training options") argparser.add_argument("--config", type=str, required=False, default=None, help="JSON config file to load options from") args, argv = argparser.parse_known_args() if args.config is not None: print(f"Loading training config from {args.config}.") with open(args.config, 'rt') as f: args.__dict__.update(json.load(f)) if len(argv) > 0: print(f"Config .json loaded but there are additional CLI arguments -- these will override values in {args.config}.") else: print("No config file specified, using command line args")
有三个点需要注意:
- parse_known_args,由于此处我们只add了config这一个参数,所以除了config之外的命令行参数都会忽略掉。
- args, argv = argparser.parse_known_args(),这个函数的返回值,前者应该是一个命名空间,只包括config这一个参数,后者应该是去掉--config之后其他的argv,这个就会用到下面的if判断中去。
- args.__dict__.update(json.load(f)),使用json中的项目更新args的命名空间。
接下来,如果使用命令行参数临时override一些args,应该如何是好:
argparser = argparse.ArgumentParser(description="EveryDream2 Training options") argparser.add_argument(XXX) ... # load CLI args to overwrite existing config args args = argparser.parse_args(args=argv, namespace=args) print(f" Args:") pprint.pprint(vars(args))
有几个点需要注意:
- 需要新建一个argparser来处理除了config之外的命令行参数。
- parse_args的参数不再留空,而是继承自上一个argparser的返回值,这样就是补全之前的命名空间。
- 使用vars加上pprint可以美观地输出args,需要注意在此之前要import pprint