?【Python】Python中好用的命令行參數(shù)解析模塊
argparse是python內(nèi)置的一個(gè)用于命令項(xiàng)選項(xiàng)與參數(shù)解析的標(biāo)準(zhǔn)模塊,不需要安裝,上手也容易,本文將通過(guò)示例代碼介紹argparse的相關(guān)用法。
1.argparse四步使用法
argparse的使用可以概括為4步使用法:
導(dǎo)入模塊 創(chuàng)建解析器 添加參數(shù) 解析參數(shù)
#?1.導(dǎo)入模塊
import?argparse
def?get_parser():
????#?2.創(chuàng)建解析器
????parser?=?argparse.ArgumentParser()
????#?3.添加參數(shù)
????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.解析參數(shù)
????hp?=?parser.parse_args()
????return?hp
if?__name__?==?"__main__":
????args?=?get_parser()
????print(args.__dict__)
2.argparse使用示例
上面已經(jīng)給出了一個(gè)完整的使用示例圖,接下來(lái)將逐個(gè)講解。(??這菜上得有點(diǎn)快,我們慢慢吃慢慢消化)
2.0 ?參數(shù)類型與默認(rèn)值
參數(shù)支持各種類型,比如字符串、數(shù)值、布爾變量(boolean)等。在添加參數(shù)時(shí)可以通過(guò)type參數(shù)指定參數(shù)的類型,有效約束命令行中的參數(shù)。
另外通過(guò)default參數(shù)可以指定默認(rèn)值,如果命令行中未給出參數(shù),則參數(shù)取值為默認(rèn)值。
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)
假設(shè)我們只添加了上面這幾個(gè)參數(shù),接著我們執(zhí)行下面的語(yǔ)句進(jìn)行幾組測(cè)試并查看測(cè)試結(jié)果。可以看到argparse模塊對(duì)傳入的參數(shù)進(jìn)行了校驗(yàn),類型不符合時(shí)會(huì)直接拋出錯(cuò)誤。當(dāng)然這里面也涉及到了自動(dòng)轉(zhuǎn)換參數(shù)類型,轉(zhuǎn)換后滿足類型約束的也可以正常運(yùn)行。
默認(rèn)值
#??python3?train.py???
{'trainData':?'data/train.json',?'validData':?'data/dev.json',?'num_epochs':?20,?'batch_size':?32,?'lr':?5e-05,?'freeze_bert':?True}
修改參數(shù)值
#??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 關(guān)于布爾(boolean)類型的參數(shù)
單獨(dú)將布爾類型參數(shù)抽離出來(lái)講,是因?yàn)閍rgparse在處理布爾類型參數(shù)時(shí)不能自動(dòng)轉(zhuǎn)換參數(shù)類型。
下面的測(cè)試說(shuō)明無(wú)論在命令行中給參數(shù)freeze_bert傳入什么值,它的值總是為默認(rèn)值(這里因?yàn)榻馕龅膮?shù)是作為對(duì)象屬性存在的,所以可使用print(f"freeze_bert:{args.freeze_bert}")僅看freeze_bert參數(shù)的值)。
#?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
那么想要命令行接收一個(gè)能夠返回boolean類型值的參數(shù)就不可能了嗎?
當(dāng)然不是。本文先例舉一個(gè)簡(jiǎn)單的可選方案:使用action參數(shù),對(duì)取值為T(mén)rue/False類型的參數(shù),在add_argument方法中加入?yún)?shù)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")
如果指定的參數(shù)出現(xiàn),那么action="store_true"/"store_false"起作用,參數(shù)值相應(yīng)地會(huì)被存儲(chǔ)為T(mén)rue/False。如果不出現(xiàn),那么參數(shù)值為默認(rèn)值。
#?python3?train.py???????????????????
freeze_bert:False
#?python3?train.py?--freeze_bert?????
freeze_bert:True
2.2 參數(shù)種類
參數(shù)可分為可選參數(shù)和必需參數(shù)。
可選參數(shù)
除前文例子中雙下劃線指定外(如:“--freeze_bert”),還可以通過(guò)單下劃線指定可選參數(shù)(如:“-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
必需參數(shù)
必需參數(shù)通過(guò)required參數(shù)指定。這里我們修改下參數(shù)log_dir的指定定方式并進(jìn)行相關(guān)測(cè)試。測(cè)試結(jié)果可見(jiàn),如果沒(méi)在命令行中給必需參數(shù)賦值,程序會(huì)報(bào)錯(cuò)。
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 可選值
除設(shè)定參數(shù)類型、修改參數(shù)值、要求參數(shù)為必需參數(shù)或可選參數(shù)外,我們還可以約束參數(shù)的可取值。這里choices參數(shù)可以將參數(shù)限制為給定列表。
我們?cè)黾右粋€(gè)參數(shù),
parser.add_argument("--pretrained_path","-prep",?type=str,choices=["bert-base-chinese","bert-base-uncased","bert-large-uncased"])
然后進(jìn)行下面的測(cè)試:
#??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.總結(jié)
argparse模塊還有其他一些使用示例,比如目標(biāo)、互斥參數(shù)、追加操作等等,后續(xù)篇章我們?cè)賮?lái)介紹。
往期精彩回顧
