当你想要在终端窗口(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模块还有其他一些使用示例,比如目标互斥参数追加操作等等,后续篇章我们再来介绍。


AI基础下载机器学习交流qq群955171419