Python argparse標(biāo)準(zhǔn)庫(kù)快速入門(mén)

Python是一門(mén)非常好用的腳本語(yǔ)言着绊,自然使用它來(lái)開(kāi)發(fā)命令行程序也比較方便。而且Python的標(biāo)準(zhǔn)庫(kù)中有一個(gè)名為argparse的庫(kù)刨沦,可以非常方便的讓我們把命令行參數(shù)轉(zhuǎn)換成所需的數(shù)據(jù)格式仿便。下面就讓我們來(lái)看看如何使用argparse標(biāo)準(zhǔn)庫(kù)吧。

如果想詳細(xì)了解argparse的話慷丽,可以查看Python官方文檔,目前已經(jīng)出了中文版文檔鳄哭,極大的方便了我們中國(guó)開(kāi)發(fā)者要糊,雖然有些地方?jīng)]有完整翻譯,但是已經(jīng)完全夠用了妆丘。

初見(jiàn)argparse

首先來(lái)看看argparse的基本用法锄俄,下面是最簡(jiǎn)單的一個(gè)例子∩准穑可以看到argparse標(biāo)準(zhǔn)庫(kù)其實(shí)用起來(lái)很簡(jiǎn)單奶赠,分成三個(gè)步驟:

  1. 創(chuàng)建ArgumentParser對(duì)象
  2. 使用add_argument方法添加參數(shù)
  3. 使用parse_args方法接受并解析對(duì)象

下面我們就依次來(lái)看看這些步驟吧。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-from', type=str)
parser.add_argument('-to', type=str, default='everyone')

args = parser.parse_args('-from yitian'.split(' '))
print(args)

# 運(yùn)行結(jié)果
# Namespace(from='yitian', to='everyone')

ArgumentParser

ArgumentParser是最重要的一個(gè)類(lèi)药有,我們要使用argparse標(biāo)準(zhǔn)庫(kù)就必然需要?jiǎng)?chuàng)建這個(gè)類(lèi)的實(shí)例毅戈。如果有需要的話苹丸,可以通過(guò)在構(gòu)造函數(shù)中設(shè)置各種參數(shù)的方式來(lái)修改ArgumentParser類(lèi)的行為。由于參數(shù)項(xiàng)比較多苇经,所以官方文檔建議我們使用關(guān)鍵字參數(shù)的方式來(lái)添加參數(shù)赘理。

  • prog - 程序的名稱(默認(rèn):sys.argv[0]),默認(rèn)是Python程序的文件名
  • usage - 描述程序用途的字符串(默認(rèn)值:從添加到解析器的參數(shù)生成)
  • description - 在參數(shù)幫助文檔之前顯示的文本(默認(rèn)值:無(wú))
  • epilog - 在參數(shù)幫助文檔之后顯示的文本(默認(rèn)值:無(wú))
  • parents - 一個(gè) ArgumentParser 對(duì)象的列表扇单,它們的參數(shù)也應(yīng)包含在內(nèi)商模。假如多個(gè)parser有一些可以共享的參數(shù),可以通過(guò)設(shè)置子parser的方式來(lái)共享
  • formatter_class - 用于自定義幫助文檔輸出格式的類(lèi)
  • prefix_chars - 可選參數(shù)的前綴字符集合(默認(rèn)值:'-')
  • fromfile_prefix_chars - 當(dāng)需要從文件中讀取其他參數(shù)時(shí)蜘澜,用于標(biāo)識(shí)文件名的前綴字符集合(默認(rèn)值:None
  • argument_default - 參數(shù)的全局默認(rèn)值(默認(rèn)值: None)阻桅,假如需要給所有參數(shù)指定一個(gè)相通的默認(rèn)值,可以修改這個(gè)兼都,如果希望全局禁用默認(rèn)值,可以使用argparse.SUPRESS
  • conflict_handler - 解決沖突選項(xiàng)的策略(通常是不必要的)
  • add_help - 為解析器添加一個(gè) -h/--help 選項(xiàng)(默認(rèn)值: True
  • allow_abbrev - 如果縮寫(xiě)是無(wú)歧義的稽寒,則允許縮寫(xiě)長(zhǎng)選項(xiàng) (默認(rèn)值:True

add_argument方法

有了Parser實(shí)例扮碧,就可以調(diào)用它的add_argument方法來(lái)添加程序可以接受的參數(shù)了。這個(gè)參數(shù)比較復(fù)雜杏糙,功能也十分強(qiáng)大慎王。

  • name or flags - 一個(gè)命名或者一個(gè)選項(xiàng)字符串的列表,例如 foo-f, --foo宏侍。
  • action - 當(dāng)參數(shù)在命令行中出現(xiàn)時(shí)使用的動(dòng)作基本類(lèi)型赖淤。
  • nargs - 命令行參數(shù)應(yīng)當(dāng)消耗的數(shù)目。
  • const - 被一些 actionnargs 選擇所需求的常數(shù)谅河。
  • default - 當(dāng)參數(shù)未在命令行中出現(xiàn)時(shí)使用的值咱旱。
  • type - 命令行參數(shù)應(yīng)當(dāng)被轉(zhuǎn)換成的類(lèi)型。
  • choices - 可用的參數(shù)的容器绷耍。
  • required - 此命令行選項(xiàng)是否可省略 (僅選項(xiàng)可用)吐限。
  • help - 一個(gè)此選項(xiàng)作用的簡(jiǎn)單描述。
  • metavar - 在使用方法消息中使用的參數(shù)值示例褂始。
  • dest - 被添加到 parse_args() 所返回對(duì)象上的屬性名诸典。

參數(shù)名

方法的第一個(gè)參數(shù)是參數(shù)名稱,可以是一個(gè)字符串(name)或者是-開(kāi)頭的一組字符串(flags)崎苗,前者是位置參數(shù)狐粱,會(huì)按照添加的順序被讀取胆数;后者是關(guān)鍵字參數(shù)肌蜻,可以以任意順序指定。如果指定的是關(guān)鍵字參數(shù)(flags)幅慌,可以同時(shí)添加縮寫(xiě)和完整名宋欺,它們分別需要用---來(lái)做前綴。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('foo')
parser.add_argument('bar')
parser.add_argument('-f', '--ff', action='store_true')

args = parser.parse_args('FOO BAR -f'.split(' '))
print(args)
args = parser.parse_args('--ff BAR FOO'.split(' '))
print(args)

'''運(yùn)行結(jié)果,注意指定的參數(shù)和獲取到的結(jié)果的不同
Namespace(bar='BAR', ff=True, foo='FOO')
Namespace(bar='FOO', ff=True, foo='BAR')
'''

action(行為)

接下來(lái)介紹的參數(shù)都是關(guān)鍵字參數(shù)齿诞,可以按需制定酸休。這里比較重要的一個(gè)是action,它指定了讀取參數(shù)接下來(lái)要做什么祷杈。這部分可以看官方文檔斑司,介紹的比較全面,而且有對(duì)應(yīng)的例子但汞。我這里只簡(jiǎn)單介紹一下宿刮。

  • store和store_const用來(lái)保存具體的值,他們之間有一些區(qū)別私蕾,一會(huì)再介紹僵缺。
  • store_true和store_false比較方便,可以用來(lái)設(shè)置一些開(kāi)關(guān)參數(shù)踩叭。例如我想指定-f的時(shí)候開(kāi)啟某個(gè)功能磕潮,忽略這個(gè)參數(shù)的時(shí)候不執(zhí)行,就可以把它的行為指定成store_true容贝,然后在程序中就可以得到f名字的參數(shù)真值自脯,然后簡(jiǎn)單的條件判斷就可以了。
  • append和append_const會(huì)將參數(shù)存儲(chǔ)成一個(gè)列表斤富。
  • count會(huì)存儲(chǔ)參數(shù)出現(xiàn)的次數(shù)膏潮。常見(jiàn)用法是指定日志輸出級(jí)別,例如有的程序-v會(huì)顯示簡(jiǎn)單輸出满力,-vv會(huì)顯示復(fù)雜輸出焕参。

甚至如果需求更復(fù)雜的話,還可以自己實(shí)現(xiàn)一個(gè)新的Action類(lèi)油额,然后添加給add_argument方法龟糕。

nargs(參數(shù)數(shù)目)

這個(gè)參數(shù)指定你的程序可以接受的參數(shù)個(gè)數(shù),可以使用以下幾個(gè)值:

  • N(一個(gè)正整數(shù))悔耘,表示后面的N個(gè)值會(huì)被讀取為參數(shù)讲岁,注意指定為1的話會(huì)變成一個(gè)單元素列表。
  • ?衬以,和正則表達(dá)式里的概念差不多缓艳,后面的一個(gè)值會(huì)被讀取,如果沒(méi)有的話會(huì)從default讀入看峻。
  • +阶淘,后面的多個(gè)值會(huì)被讀取,如果沒(méi)有會(huì)拋出異常互妓。
  • ?溪窒,后面的多個(gè)值會(huì)被讀取坤塞,沒(méi)有值的話也可以。
  • argparse.REMAINDER澈蚌,它會(huì)將后面所有值讀取為一個(gè)參數(shù)摹芙,通常用作向其他命令行傳遞參數(shù)用。

默認(rèn)情況下nargs會(huì)按照action的類(lèi)型來(lái)判斷參數(shù)個(gè)數(shù)宛瞄,store和store_const會(huì)讀取后面的一個(gè)值作為參數(shù)浮禾。

const

這個(gè)參數(shù)需要和帶有const的action來(lái)配合使用。

default

指定參數(shù)的默認(rèn)值份汗。這里有一個(gè)很有趣的點(diǎn)盈电,如果你看官方文檔比較仔細(xì)的話,可能會(huì)產(chǎn)生一個(gè)和我一樣的疑問(wèn):store_const和const配合使用可以指定默認(rèn)值杯活,而store和default也可以指定默認(rèn)值匆帚,那么它們之間有什么區(qū)別呢?其實(shí)區(qū)別還是蠻大的旁钧,看看下面這個(gè)例子就明白了卷扮。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-foo', action='store', nargs='?', default=10, const=20)

print(parser.parse_args('-foo 0'.split(' ')))
print(parser.parse_args('-foo'.split(' ')))
print(parser.parse_args(''))

'''
Namespace(foo='0')
Namespace(foo=20)
Namespace(foo=10)
'''
  1. 當(dāng)foo參數(shù)完全忽略的時(shí)候,會(huì)使用default的值均践。
  2. 當(dāng)指定了foo參數(shù),但沒(méi)有指定后面的值時(shí)摩幔,會(huì)使用const的值彤委。
  3. 當(dāng)指定了foo參數(shù)和后面的值時(shí),會(huì)使用我們指定的值或衡。

type

這個(gè)是指定參數(shù)類(lèi)型的焦影,int、float封断、str那些斯辰。當(dāng)然比較特殊的一個(gè)是open,它會(huì)將參數(shù)作為文件來(lái)打開(kāi)坡疼。

如果默認(rèn)的open還不能滿足彬呻,還可以使用argparse.FileType,它提供了讀寫(xiě)模式柄瑰、文件編碼闸氮、緩沖區(qū)大小等詳細(xì)設(shè)置。

parser.add_argument('bar', type=argparse.FileType('w'))

甚至有需求的話教沾,這里還可以使用我們自己的函數(shù)蒲跨,只要它的參數(shù)是一個(gè)字符串,返回值是轉(zhuǎn)換以后的值就可以授翻。

choices

如果確認(rèn)參數(shù)范圍限定是幾個(gè)定值或悲,可以使用choices參數(shù)來(lái)指定孙咪,可接受的值包括字面值列表以及range函數(shù)。

required

指定參數(shù)是否是必須的巡语。

metavar和dest

metavar參數(shù)用來(lái)指定參數(shù)的顯示名稱翎蹈,而dest用來(lái)指定參數(shù)底層使用的屬性名。

注意下面的程序輸出捌臊,foo參數(shù)只修改了metavar杨蛋,所以在幫助信息輸出中發(fā)生了變化,但是在Namespace底層仍然使用foo保存值理澎。而bar參數(shù)修改了dest逞力,所以底層屬性名發(fā)生了變化,但是在幫助信息中并沒(méi)有什么改變糠爬。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-foo', metavar='foooo')
parser.add_argument('-bar', dest='barrrr')

parser.print_help()
print(parser.parse_args(''))

'''
usage: argparse_sample.py [-h] [-foo foooo] [-bar bar]

optional arguments:
  -h, --help  show this help message and exit
  -foo foooo
  -bar bar
Namespace(barrrr=None, foo=None)
'''

help

有條件的話最好給每個(gè)參數(shù)添加幫助信息寇荧,這樣使用者在用-h命令的時(shí)候就可以看到參數(shù)的幫助信息了。

parse_args方法

編輯好了參數(shù)执隧,就可以調(diào)用parse_args方法來(lái)處理參數(shù)了揩抡,它會(huì)返回一個(gè)命名空間對(duì)象,包含了解析之后的參數(shù)镀琉。如果要測(cè)試方法的話峦嗤,可以手動(dòng)給它傳遞一組參數(shù),否則的話屋摔,它會(huì)自動(dòng)從命令行參數(shù)讀取烁设。另外它還支持幾個(gè)比較有用的特性:

  • 如果參數(shù)比較長(zhǎng),可以使用等號(hào)來(lái)連接參數(shù)與值钓试,例如-foo=bar装黑。
  • 如果參數(shù)是單字母長(zhǎng)度的,可以將參數(shù)和值直接寫(xiě)在一起弓熏。
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-foo')
parser.add_argument('-b')

print(parser.parse_args('-foo=bar'.split()))
print(parser.parse_args('-bX'.split()))

'''
Namespace(b=None, foo='bar')
Namespace(b='X', foo=None)
'''

另外還支持默認(rèn)無(wú)歧義的參數(shù)縮寫(xiě)恋谭。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f1aaaaaaaaaa')
parser.add_argument('-f2aaaaaaaaaa')

print(parser.parse_args('-f1 a -f2 b'.split(' ')))

命名空間對(duì)象

前面也看到了,解析完參數(shù)返回的值是命名空間對(duì)象挽鞠,它用起來(lái)非常簡(jiǎn)單疚颊,直接訪問(wèn)屬性值就可以了。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-a')
parser.add_argument('-b')

args = parser.parse_args('-a a -b b'.split(' '))
print(args.a)

# a

其他特性

argparse還支持一些其他特性信认,這里就不多做介紹了串稀,詳情請(qǐng)直接參考官方文檔。

  • 子parser狮杨。有些程序支持子命令母截,這時(shí)候可以使用子parser創(chuàng)建更復(fù)雜的parser。
  • FileType橄教。更詳細(xì)的設(shè)置文件參數(shù)的方法清寇。
  • 參數(shù)組喘漏。如果參數(shù)比較多,可以使用參數(shù)組的方式將功能相近的參數(shù)進(jìn)行分組华烟,這樣不管是開(kāi)發(fā)人員還是使用人員都能更清晰的使用參數(shù)翩迈。
  • 互斥參數(shù)組。如果某些參數(shù)不能同時(shí)使用盔夜,可以將它們加到互斥參數(shù)組中负饲。
  • 部分解析。默認(rèn)情況下parse_argument在遇到未知參數(shù)的時(shí)候會(huì)報(bào)錯(cuò)喂链,如果需要保存這些參數(shù)傳遞給其他命令行的時(shí)候返十,可以使用parse_known_args方法。它不會(huì)因?yàn)槲粗獏?shù)報(bào)錯(cuò)椭微, 而且會(huì)將所有不認(rèn)識(shí)的參數(shù)存儲(chǔ)成一個(gè)列表作為第二個(gè)返回值洞坑。

簡(jiǎn)單實(shí)例

扯了大半天,大家可能還是有點(diǎn)不會(huì)用argparse蝇率,不過(guò)其實(shí)只要看一個(gè)簡(jiǎn)單的例子就可以了迟杂。保存下面的文件,然后用命令行調(diào)用本慕,看看不同的參數(shù)會(huì)有什么輸出排拷。

import argparse

parser = argparse.ArgumentParser(prog='ParserSample',
                                 description='簡(jiǎn)單實(shí)例程序,學(xué)習(xí)如何解析命令行參數(shù)',
                                 epilog='很簡(jiǎn)單就可以學(xué)會(huì)')

parser.add_argument('greeting', type=str, help='問(wèn)候信息锅尘,必需')
parser.add_argument('-fromm', default='yitian', type=str, help='發(fā)送人监氢,默認(rèn)是易天')
parser.add_argument('-to', default='everyone', type=str, nargs='*', help='接收人,默認(rèn)是所有人')
parser.add_argument('-p', action='store_true', help='是否添加感嘆號(hào)')

args = parser.parse_args()

output = f'{args.fromm} say {args.greeting} to {args.to}'
if args.p:
    output = output + '!'

print(output)

'''
usage: ParserSample [-h] [-fromm FROMM] [-to [TO [TO ...]]] [-p] greeting

簡(jiǎn)單實(shí)例程序鉴象,學(xué)習(xí)如何解析命令行參數(shù)

positional arguments:
  greeting           問(wèn)候信息,必需

optional arguments:
  -h, --help         show this help message and exit
  -fromm FROMM       發(fā)送人何鸡,默認(rèn)是易天
  -to [TO [TO ...]]  接收人纺弊,默認(rèn)是所有人
  -p                 是否添加感嘆號(hào)

很簡(jiǎn)單就可以學(xué)會(huì)
'''
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市骡男,隨后出現(xiàn)的幾起案子淆游,更是在濱河造成了極大的恐慌,老刑警劉巖隔盛,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犹菱,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡吮炕,警方通過(guò)查閱死者的電腦和手機(jī)腊脱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)龙亲,“玉大人陕凹,你說(shuō)我怎么就攤上這事悍抑。” “怎么了杜耙?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵搜骡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我佑女,道長(zhǎng)记靡,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任团驱,我火速辦了婚禮摸吠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘店茶。我一直安慰自己蜕便,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布贩幻。 她就那樣靜靜地躺著轿腺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丛楚。 梳的紋絲不亂的頭發(fā)上族壳,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音趣些,去河邊找鬼仿荆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛坏平,可吹牛的內(nèi)容都是我干的拢操。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼舶替,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼令境!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起顾瞪,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤舔庶,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后陈醒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體惕橙,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年钉跷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弥鹦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡爷辙,死狀恐怖惶凝,靈堂內(nèi)的尸體忽然破棺而出吼虎,到底是詐尸還是另有隱情,我是刑警寧澤苍鲜,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布思灰,位于F島的核電站,受9級(jí)特大地震影響混滔,放射性物質(zhì)發(fā)生泄漏洒疚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一坯屿、第九天 我趴在偏房一處隱蔽的房頂上張望油湖。 院中可真熱鬧,春花似錦领跛、人聲如沸乏德。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)喊括。三九已至,卻和暖如春矢棚,著一層夾襖步出監(jiān)牢的瞬間郑什,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工蒲肋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蘑拯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓兜粘,卻偏偏與公主長(zhǎng)得像申窘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子孔轴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容