​【Python】Python中好用的命令行参数解析模块

机器学习初学者

共 7555字,需浏览 16分钟

 ·

2022-03-15 15:47

大家好,我是小喵!
关注和星标『AI算法小喵』和小喵一起学习AI算法!
 👆点击关注|设为星标|干货速递👆

当你想要在终端窗口(ubuntu的终端窗口或windows的命令行窗口)来向程序传入参数并让程序运行时,就需要用到命令行参数解析模块。Python本身提供了三个命令行参数解析模块:getopt、optparse、argparse,三者之中argparse相对更好用。

argparse是python内置的一个用于命令项选项与参数解析的标准模块,不需要安装,上手也容易,本文将通过示例代码介绍argparse的相关用法。

1.argparse四步使用法

argparse的使用可以概括为4步使用法:

  1. 导入模块
  2. 创建解析器
  3. 添加参数
  4. 解析参数
# 1.导入模块
import argparse

def get_parser():
    # 2.创建解析器
    parser = argparse.ArgumentParser()
    # 3.添加参数
    parser.add_argument("--trainData"type=str, default="data/train.json")
    parser.add_argument("--validData"type=str, default="data/dev.json")
    parser.add_argument("--num_epochs"type=int, default=20)
    parser.add_argument("--batch_size"type=int, default=32)
    parser.add_argument("--lr"type=float, default=5e-5)

    parser.add_argument("--freeze_bert", default=False, action="store_true",
                        help="If provided, freeze the layers of bert")
    parser.add_argument("--emb_dropout", default=True,action="store_true",
                        help="If provided, add dropout to the output embedding of bert")
    parser.add_argument("--dropout_rate"type=float, default=0.5)
    parser.add_argument("--num_layers", dest="num_layers", default=1)
    parser.add_argument("--hidden_units", dest="hidden_units", default=128)

    parser.add_argument("--log_dir"type=str, default="logs/")
    parser.add_argument("--model_path"type=str, default="checkpoints/")
    # 4.解析参数
    hp = parser.parse_args()
    return hp

if __name__ == "__main__":
    args = get_parser()
    print(args.__dict__)

2.argparse使用示例

上面已经给出了一个完整的使用示例图,接下来将逐个讲解。(😊这菜上得有点快,我们慢慢吃慢慢消化)

2.0  参数类型与默认值

参数支持各种类型,比如字符串、数值、布尔变量(boolean)等。在添加参数时可以通过type参数指定参数的类型,有效约束命令行中的参数。

另外通过default参数可以指定默认值,如果命令行中未给出参数,则参数取值为默认值。

parser.add_argument("--trainData"type=str, default="data/train.json")
parser.add_argument("--validData"type=str, default="data/dev.json")
parser.add_argument("--num_epochs"type=int, default=20)
parser.add_argument("--batch_size"type=int, default=32)
parser.add_argument("--lr"type=float, default=5e-5)
parser.add_argument("--freeze_bert",type=bool, default=True)

假设我们只添加了上面这几个参数,接着我们执行下面的语句进行几组测试并查看测试结果。可以看到argparse模块对传入的参数进行了校验,类型不符合时会直接抛出错误。当然这里面也涉及到了自动转换参数类型,转换后满足类型约束的也可以正常运行。

  • 默认值
#  python3 train.py   
{'trainData''data/train.json''validData''data/dev.json''num_epochs': 20, 'batch_size': 32, 'lr': 5e-05, 'freeze_bert': True}
  • 修改参数值
#  python3 train.py --lr 0.005       
{'trainData''data/train.json''validData''data/dev.json''num_epochs': 20, 'batch_size': 32, 'lr': 0.005, 'freeze_bert': True}
#  python3 train.py --lr 5       
{'trainData''data/train.json''validData''data/dev.json''num_epochs': 20, 'batch_size': 32, 'lr': 5, 'freeze_bert': True}

# train.py --num_epochs 30  
{'trainData''data/train.json''validData''data/dev.json''num_epochs': 30, 'batch_size': 32, 'lr': 5e-05, 'freeze_bert': True}
# train.py --num_epochs "30"  
{'trainData''data/train.json''validData''data/dev.json''num_epochs': 30, 'batch_size': 32, 'lr': 5e-05, 'freeze_bert': True}

# python3 train.py --num_epochs "三十"
usage: train.py [-h] [--trainData TRAINDATA] [--validData VALIDDATA]
                [--num_epochs NUM_EPOCHS] [--batch_size BATCH_SIZE] [--lr LR]
                [--freeze_bert FREEZE_BERT]
train.py: error: argument --num_epochs: invalid int value: '三十'
# python3 train.py --num_epochs 30.5 
usage: train.py [-h] [--trainData TRAINDATA] [--validData VALIDDATA]
                [--num_epochs NUM_EPOCHS] [--batch_size BATCH_SIZE] [--lr LR]
                [--freeze_bert FREEZE_BERT]
train.py: error: argument --num_epochs: invalid int value: '30.5'

2.1 关于布尔(boolean)类型的参数

单独将布尔类型参数抽离出来讲,是因为argparse在处理布尔类型参数时不能自动转换参数类型。

下面的测试说明无论在命令行中给参数freeze_bert传入什么值,它的值总是为默认值(这里因为解析的参数是作为对象属性存在的,所以可使用print(f"freeze_bert:{args.freeze_bert}")仅看freeze_bert参数的值)。

# python3 train.py --freeze_bert 1    
freeze_bert:True
# python3 train.py --freeze_bert 0
freeze_bert:True

# python3 train.py --freeze_bert False
freeze_bert:True
# python3 train.py --freeze_bert True 
freeze_bert:True

那么想要命令行接收一个能够返回boolean类型值的参数就不可能了吗?

当然不是。本文先例举一个简单的可选方案:使用action参数,对取值为True/False类型的参数,在add_argument方法中加入参数action="store_true"/"store_false"

parser.add_argument("--trainData"type=str, default="data/train.json")
parser.add_argument("--validData"type=str, default="data/dev.json")
parser.add_argument("--num_epochs"type=int, default=20)
parser.add_argument("--batch_size"type=int, default=32)
parser.add_argument("--lr"type=float, default=5e-5)
# parser.add_argument("--freeze_bert",type=bool, default=True)
parser.add_argument("--freeze_bert", default=False, action="store_true",help="If provided, freeze the layers of bert")

如果指定的参数出现,那么action="store_true"/"store_false"起作用,参数值相应地会被存储为True/False。如果不出现,那么参数值为默认值。

# python3 train.py                   
freeze_bert:False
# python3 train.py --freeze_bert     
freeze_bert:True

2.2 参数种类

参数可分为可选参数必需参数

  • 可选参数

除前文例子中双下划线指定外(如:“--freeze_bert”),还可以通过单下划线指定可选参数(如:“-fb”

parser.add_argument("--freeze_bert""-fb",default=False, action="store_true",help="If provided, freeze the layers of bert")
# python3 train.py              
freeze_bert:False

# python3 train.py -fb          
freeze_bert:True
  • 必需参数

必需参数通过required参数指定。这里我们修改下参数log_dir的指定定方式并进行相关测试。测试结果可见,如果没在命令行中给必需参数赋值,程序会报错。

parser.add_argument("--log_dir"type=str, required=True)
# python3 train.py --log_dir logs/
{'trainData''data/train.json''validData''data/dev.json''num_epochs': 20, 'batch_size': 32, 'lr': 5e-05, 'freeze_bert': False, 'emb_dropout': True, 'dropout_rate': 0.5, 'num_layers': 1, 'hidden_units': 128, 'log_dir''logs/''model_path''checkpoints/'}

# python3 train.py                
usage: train.py [-h] [--trainData TRAINDATA] [--validData VALIDDATA]
                [--num_epochs NUM_EPOCHS] [--batch_size BATCH_SIZE] [--lr LR]
                [--freeze_bert] [--emb_dropout] [--dropout_rate DROPOUT_RATE]
                [--num_layers NUM_LAYERS] [--hidden_units HIDDEN_UNITS]
                --log_dir LOG_DIR [--model_path MODEL_PATH]
train.py: error: the following arguments are required: --log_dir

2.3 可选值

除设定参数类型、修改参数值、要求参数为必需参数或可选参数外,我们还可以约束参数的可取值。这里choices参数可以将参数限制为给定列表。

我们增加一个参数,

parser.add_argument("--pretrained_path","-prep"type=str,choices=["bert-base-chinese","bert-base-uncased","bert-large-uncased"])

然后进行下面的测试:

#  python3 train.py -prep bert-base-chinese --log_dir logs/
{'trainData''data/train.json''validData''data/dev.json''num_epochs': 20, 'batch_size': 32, 'lr': 5e-05, 'freeze_bert': False, 'emb_dropout': True, 'dropout_rate': 0.5, 'num_layers': 1, 'hidden_units': 128, 'log_dir''logs/''model_path''checkpoints/''pretrained_path''bert-base-chinese'}

# python3 train.py -prep bert-base-cased --log_dir logs/
usage: train.py [-h] [--trainData TRAINDATA] [--validData VALIDDATA]
                [--num_epochs NUM_EPOCHS] [--batch_size BATCH_SIZE] [--lr LR]
                [--freeze_bert] [--emb_dropout] [--dropout_rate DROPOUT_RATE]
                [--num_layers NUM_LAYERS] [--hidden_units HIDDEN_UNITS]
                --log_dir LOG_DIR [--model_path MODEL_PATH]
                [--pretrained_path {bert-base-chinese,bert-base-uncased,bert-large-uncased}]
train.py: error: argument --pretrained_path/-prep: invalid choice: 'bert-base-cased' (choose from 'bert-base-chinese''bert-base-uncased''bert-large-uncased')

3.总结

argparse模块还有其他一些使用示例,比如目标互斥参数追加操作等等,后续篇章我们再来介绍。

往期精彩回顾





浏览 88
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报