1. 程式人生 > >python argparse:命令列引數解析詳解

python argparse:命令列引數解析詳解

## 簡介 本文介紹的是***[argparse](https://docs.python.org/3/library/argparse.html)***模組的基本使用方法,尤其詳細介紹**add_argument**內建方法各個引數的使用及其效果。 本文翻譯自[argparse的官方說明](https://docs.python.org/3/library/argparse.html),並加上一些筆者的理解 ```Python import argparse parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('integers', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('--sum', dest='accumulate', action='store_const', const=sum, default=max, help='sum the integers (default: find the max)') args = parser.parse_args() print(args.accumulate(args.integers)) ``` 如上示例,*argparse*模組的基本使用包含5個步驟: 1. import模組:*import argparse* 2. 獲解析器物件:*argparse.ArgumentParser* 3. 利用解析器物件內建方法,新增引數解析規則:*add_argument* 4. 利用解析器物件內建方法,開始解析引數,獲取解析結果物件:*parse_args* 5. 從解析結果物件中,獲取引數值:*parse_args* ## 解析器類(ArgumentParser) 在第2步中,我們通過```ArgumentParser()```函式的呼叫獲取瞭解析器物件```ArgumentParser```。 在瞭解解析器物件的各個成員之前,我們先對一段正常的說明文字進行區間劃分 ``` # usage欄位 usage: 程式名 [-h|--help] ..... # Description欄位 程式功能描述 # 位置引數說明(必選) positional arguments: ... # 可選引數說明 optional arguments: ... # 補充說明欄位 ... ``` 例如 ``` usage: PROG [-h] [--foo [FOO]] bar [bar ...] bar help positional arguments: bar bar help optional arguments: -h, --help show this help message and exit --foo [FOO] foo help And that's how you'd foo a bar ``` *關於位置引數與可選引數的理解,參考下一章節:[新增引數解析規則](#關鍵字name-or-flags)* 在上述的區間劃的認識下,我們再來看看解析器物件的成員及其功能 | 名字 | 預設值 | 功能 | | :---: | :---: | :--- | | prog | sys.argv[0] | ```-h```時顯示的程式名 | | usage | - | usage欄位描述 | | description | None | description欄位描述 | | epilog | None | 補充欄位描述 | | parents | None | 從父(公共)解析器中繼承所有的引數選項 | | formatter_class | None | 定製說明文字的顯示風格 | | prefix_class | - | 定製字首字元,例如字首**"-b"**改為**“+b"** | | add_help | True | 是否使能顯示引數 ```-h --help``` | | allow_abbrev | True | 是否支援長引數 | | fromfile_prefix_chars | None | 略 | | argument_default | None | 略 | | conflict_handler | None | 略 | 比較常用的是***description***,例如: ``` parser = argparse.ArgumentParser(description='Process some integers.') ``` 或者 ``` parser = argparse.ArgumentParser() parser.descritpioin="Process some integers." ``` ## 新增引數解析規則(add_argument) ***add_argument***是解析器類***ArgumentParser***的內建方法,用於向解析器新增引數解析規則 ``` ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type] [, choices][, required][, help][, metavar][, dest]) ``` 內建方法支援以下的**關鍵字**,我們會對每一個關鍵字及其效果做進一步說明 | 關鍵字 | 簡介 | | :--- | :---- | | [name or flags](#關鍵字name-or-flags) | 引數名或者"-/--"開頭的選項,例如```foo```或者```-f, --foo``` | | [action](#關鍵字action) | 匹配到選項後的行為 | | [nargs](#關鍵字nargs) | 選項跟隨的引數個數 | | [const](#關鍵字const) | 在某些```action```和```nargs```下,使用的固定值 | | [default](#關鍵字default) | 預設值 | | [type](#關鍵字type) | 引數型別 | | [choices](#關鍵字choices) | 可選的引數值範圍 | | [required](#關鍵字required) | 選項必選or可選 | | [help](#關鍵字help) | 引數描述 | | [metavar](#關鍵字metavar) | 使用說明中顯示的引數名 | | [dest](#關鍵字dest) | 選項最終在解析結果物件中的名字 | ### 關鍵字name or flags **關鍵字name**是什麼?**flags**又是什麼?兩者有什麼差別? **name表示引數名,其賦值與位置順序相關,因此也叫位置引數名,命令列中必須賦值** **flags表示```-|--```開頭的引數名,命令列中可選引數** 例如: ``` #可選的flags引數 parser.add_argument('-f', '--foo') #必選的name位置引數 parser.add_argument('bar0') parser.add_argument('bar1') ``` 這裡假設```--foo```需要帶1個引數,那麼 ``` prog arg1 --foo arg2 arg3 ``` * arg1 是位置引數bar0的值 * arg2 是可選引數'-f, --foo'的值 * arg3 是位置引數bar1的值 換句話來說,在輸入的命令列中,除去所有```-|--```開頭的引數及其帶上的引數值之外,剩下的引數都為位置引數,其順序依次對應使用*add_argument*註冊的位置引數順序。 **在命令列呼叫中,位置引數必須賦值,即每個必選引數都要有賦值;而可選引數```(-|--)```可根據需求選擇** ### 關鍵字action 功能如其名,**關鍵字action**控制匹配到命令列選項後的行為。引數解析後不是儲存值就好了?我們繼續看看。 **關鍵字action**只支援以下值,我們稍後再詳細講解每一個值的含義: | 值 | 含義 | | :--- | :--- | | store | 儲存引數值 | | store_const | 與**關鍵字const**配合使用,儲存**關鍵字const**的值 | | store_true | 儲存值為*True* | | store_false | 儲存值為*False* | | append | 儲存多次選項值為列表 | | append_const | 與**關鍵字const**配合使用,儲存**關鍵字const**的值為列表 | | const | 儲存選項的出現次數 | | help | 效果等效於```-h```和 ```--help``` | | version | 列印版本 | #### store 儲存引數值,這也是預設的行為,我們看個例子: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo') >>> parser.parse_args('--foo 1'.split()) Namespace(foo='1') ``` 在```parse_args()```之後,```--foo```選項的值就儲存到了```parse_args()```的解析結果物件中。 我們可以這樣獲取解析結果物件的值: ```python args = parser.parse_args('--foo 1'.split()) print(args.foo) ``` 總結來說,**選項名成為了解析結果物件的成員,而選項對應的值則成了成員的值** 到這裡,我們存在2個疑惑: 1. 當同時支援```-f```和```--foo```時,生成的成員名是什麼呢?能自定義名字麼? 2. 當```PROG -f```這樣不需要帶引數的選項,儲存的成員值是什麼樣的呢? 不用急,我們繼續往下看 #### store_const 在匹配到選項後,儲存[**關鍵字const**](#關鍵字const)的值,常用於命令列中不帶引數的選項。例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action='store_const', const=42) >>> parser.parse_args(['--foo']) Namespace(foo=42) ``` 從上面的例子,我們可以看到,在匹配到```--foo```後,對應成員foo的儲存為了```const引數```的值。 但更多時候,我們不帶引數的選項更多隻是表示布林型的開關,這時候我們可用```store_true```或者```store_false``` #### store_true 和 store_false ```store_true```和```store_false```是一種特殊的```store_const```,儲存的值型別為布林型```True```或```False```。例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action='store_true') >>> parser.add_argument('--bar', action='store_false') >>> parser.add_argument('--baz', action='store_false') >>> parser.parse_args('--foo --bar'.split()) Namespace(foo=True, bar=False, baz=True) ``` 示例中有3個布林型“開關”,可以發現有以下特點: 1. ```store_true```在匹配到命令選項後,儲存為```True```;相對的,```store_false```儲存為```False``` 2. 當命令列中沒匹配到開關後,例如示例中的```baz```,則儲存為```store_false```的相反值```True``` #### append 把所有值儲存為一個列表,常用於支援多次選項的情況,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action='append') >>> parser.parse_args('--foo 1 --foo 2'.split()) Namespace(foo=['1', '2']) ``` #### append_const 與```store_const```非常相似,只是把值儲存為一個列表。此時如果沒有指定**關鍵字const**,則預設為```None```。```append_const```常用於多個不同選項值需要儲存到相同成員列表的情況。例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--str', dest='types', action='append_const', const=str) >>> parser.add_argument('--int', dest='types', action='append_const', const=int) >>> parser.parse_args('--str --int'.split()) Namespace(types=[, ]) ``` 理解上文需要知道以下前提: 1. [**關鍵字dest**](#關鍵字dest)用於指定成員名 2. 引數的值可以是各種物件,包括型別物件,即示例中的**str型別**和**int型別** 在示例中,```--str```的常量值是***str型別***,以列表形式儲存到**types成員**;```--int```的常量值是***int型別***,以列表形式儲存到**types成員** #### count 如果我們只需要統計**選項**出現的次數,此處可以用```count```,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--verbose', '-v', action='count') >>> parser.parse_args(['-vvv']) Namespace(verbose=3) ``` #### help 列印幫助資訊,功能等效於```-h|--help``` #### version 列印版本資訊,需要配合**關鍵字version**使用,例如: ```python >>> import argparse >>> parser = argparse.ArgumentParser(prog='PROG') >>> parser.add_argument('--version', action='version', version='%(prog)s 2.0') >>> parser.parse_args(['--version']) PROG 2.0 ``` ### 關鍵字nargs **關鍵字nargs**是*number argumemts*的縮寫,表示選項有多少個引數,其支援以下值: | 值 | 含義 | | :---: | :--- | | N (an integer) | 收集N個引數到列表 | | '?' | 無引數或單個引數 | | '*' | 大於等於0個引數 | | '+' | 大於等於1個引數 | | argparse.REMAINDER | 只收集不解析 | 當沒有指定**關鍵字nargs**時,其實際的值取決於**關鍵字action**,例如當```action = "store"```時,預設獲取1個引數,當```action = "store_true"```時,選項不需要帶引數。 #### N (an integer) 此處的```N```,表示一個整型數字,含義為選項需要提供N個引數。例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', nargs=2) >>> parser.add_argument('bar', nargs=1) >>> parser.parse_args('c --foo a b'.split()) Namespace(bar=['c'], foo=['a', 'b']) ``` 需要注意的是,當```nargs = 1```時,其並不等效於**關鍵字nargs**的預設情況。例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('bar0', nargs=1) >>> parser.add_argument('bar1') >>> parser.parse_args('a b'.split()) Namespace(bar0=['a'], bar1='b') ``` 可以發現,```nargs = 1```時,例如bar0,其值是一個列表,一個只有1個元素的列表;而預設情況下,就是一個元素,官方稱為```item```。 #### '?' ```nargs='?'```可以實現3種場景: 1. 輸入的命令列中,選項帶引數時,值為附帶的引數 2. 輸入的命令列中,沒有改選項時,值為**關鍵字default**的值 3. 輸入的命令列中,有選項但沒帶引數時,值為**關鍵字const**的值(只適用於可選選項(flag)) 例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', nargs='?', const='c', default='d') >>> parser.add_argument('bar', nargs='?', default='d') >>> parser.parse_args(['XX', '--foo', 'YY']) Namespace(bar='XX', foo='YY') >>> parser.parse_args(['XX', '--foo']) Namespace(bar='XX', foo='c') >>> parser.parse_args([]) Namespace(bar='d', foo='d') ``` 一個更常用的場景,是實現可選的輸入輸出檔案,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), ... default=sys.stdin) >>> parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'), ... default=sys.stdout) >>> parser.parse_args(['input.txt', 'output.txt']) Namespace(infile=<_io.TextIOWrapper name='input.txt' encoding='UTF-8'>, outfile=<_io.TextIOWrapper name='output.txt' encoding='UTF-8'>) >>> parser.parse_args([]) Namespace(infile=<_io.TextIOWrapper name='' encoding='UTF-8'>, outfile=<_io.TextIOWrapper name='' encoding='UTF-8'>) ``` 上述例子中,如果命令列沒有指定input,則使用標準輸入stdin;如果命令列沒有指定output,則使用標準輸出stdout #### '*' ```nargs=2```會限制一定要有2個引數,如果需要任意多個引數呢?我們可以用```nargs='*'```,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', nargs='*') >>> parser.add_argument('--bar', nargs='*') >>> parser.add_argument('baz', nargs='*') >>> parser.parse_args('a b --foo x y --bar 1 2'.split()) Namespace(bar=['1', '2'], baz=['a', 'b'], foo=['x', 'y']) ``` 與```nargs=N```相似,最終的值是列表型別。 #### '+' ```nargs='+'```與```nargs='*'```從功能上非常相似,唯一不同的地方在於,```nargs='+'```要求至少要有1個引數,否則會報錯。 ```'?'```,```'+'```與```'*'```的定義與正則表示式中的```?```,```+```和```*```非常相似 在正則表示式中, * ?:表示0或1個字元 * +:表示大於等於1個字元 * *:表示大於等於0個字元 我們看個例子: ```python >>> parser = argparse.ArgumentParser(prog='PROG') >>> parser.add_argument('foo', nargs='+') >>> parser.parse_args(['a', 'b']) Namespace(foo=['a', 'b']) >>> parser.parse_args([]) usage: PROG [-h] foo [foo ...] PROG: error: the following arguments are required: foo ``` #### argparse.REMAINDER ```nargs=argparse.REMAINDER```常用於收集引數後傳遞給其他的命令列解析工具,其不會解析```-|--```,只是收集所有選項到列表。 例如: ```python >>> parser = argparse.ArgumentParser(prog='PROG') >>> parser.add_argument('--foo') >>> parser.add_argument('command') >>> parser.add_argument('args', nargs=argparse.REMAINDER) >>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split())) Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B') ``` 上例中,**argparse**沒有解析```args```選項的```--arg1```,而是全部收集到了一個列表 ### 關鍵字const 在**關鍵字acton**和**關鍵字nargs**中,其實已經涉及了**關鍵字const**的所有功能。 **關鍵字const**只是儲存一個常量值,在以下兩種情況下才會使用: 1. [```action='store_const'```](#store_const)或者[```action='append_const'```](#sppend_const) 2. [```nargs='?'```](#'?') 當使用```action='store_const'```和```action='append_const'```時,**關鍵字const**必須提供,對其他的**action關鍵字**時,預設值為```None``` ### 關鍵字default 有時候,選項不帶引數,或者命令列沒對應選項,這時候就可以使用預設值,而**關鍵字default**儲存的就是預設值。預設情況下,**關鍵字default**的值為```None```。例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', default=42) >>> parser.parse_args(['--foo', '2']) Namespace(foo='2') >>> parser.parse_args([]) Namespace(foo=42) ``` 如果**關鍵字default**賦值的是字串,而**關鍵字type**有指定引數型別,那麼就會把字串轉為**關鍵字type**指定的型別,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--length', default='10', type=int) >>> parser.add_argument('--width', default=10.5, type=int) >>> parser.parse_args() Namespace(length=10, width=10.5) ``` 如果[**關鍵字nargs**](#關鍵字nargs)為```?```或者```*```,那麼default的值會在命令列沒有引數時使用,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('foo', nargs='?', default=42) >>> parser.parse_args(['a']) Namespace(foo='a') >>> parser.parse_args([]) Namespace(foo=42) ``` **關鍵字default**也提供一種特殊用法:```default=argparse.SUPPRESS```。在這種情況下,如果命令列並沒有匹配的選項,那麼並不會在**解析結果物件**中新增選項對應的成員,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', default=argparse.SUPPRESS) >>> parser.parse_args([]) Namespace() >>> parser.parse_args(['--foo', '1']) Namespace(foo='1') ``` ### 關鍵字type 預設情況下,**argparse**解析的引數預設為**字串**型別,當然也可以通過**關鍵字type**指定其他任何型別,例如```float```,```int```,甚至是檔案型別```file```, 例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('foo', type=int) >>> parser.add_argument('bar', type=open) >>> parser.parse_args('2 temp.txt'.split()) Namespace(bar=<_io.TextIOWrapper name='temp.txt' encoding='UTF-8'>, foo=2) ``` 如果**關鍵字type**指定的是檔案型別,我們還可以通過```FileType('w')以可寫形式開啟檔案,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('bar', type=argparse.FileType('w')) >>> parser.parse_args(['out.txt']) Namespace(bar=<_io.TextIOWrapper name='out.txt' encoding='UTF-8'>) ``` **關鍵字type**甚至能指定為函式,經過函式處理後的返回值作為引數值,例如: ```python >>> def perfect_square(string): ... value = int(string) ... sqrt = math.sqrt(value) ... if sqrt != int(sqrt): ... msg = "%r is not a perfect square" % string ... raise argparse.ArgumentTypeError(msg) ... return value ... >>> parser = argparse.ArgumentParser(prog='PROG') >>> parser.add_argument('foo', type=perfect_square) >>> parser.parse_args(['9']) Namespace(foo=9) >>> parser.parse_args(['7']) usage: PROG [-h] foo PROG: error: argument foo: '7' is not a perfect square ``` ### 關鍵字choices 當我們需要限制選項的值範圍,我們可以用**關鍵字choices**。**關鍵字choices**限定了引數值的可選列表,如果命令列提供的引數值不在列表中,則會報錯,例如: ```python >>> parser = argparse.ArgumentParser(prog='game.py') >>> parser.add_argument('move', choices=['rock', 'paper', 'scissors']) >>> parser.parse_args(['rock']) Namespace(move='rock') >>> parser.parse_args(['fire']) usage: game.py [-h] {rock,paper,scissors} game.py: error: argument move: invalid choice: 'fire' (choose from 'rock', 'paper', 'scissors') ``` 當然,需要注意的是,**關鍵字choice**的值必須符合**關鍵字type**指定的型別。 ### 關鍵字required 預設情況下,```-f```和```--foo```都是可選的,但如果需要改為**必選**,可以使用**關鍵字required**,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', required=True) >>> parser.parse_args(['--foo', 'BAR']) Namespace(foo='BAR') >>> parser.parse_args([]) usage: argparse.py [-h] [--foo FOO] argparse.py: error: option --foo is required ``` ### 關鍵字help **關鍵字help**是選項的說明,在```-h```或者```--help```時會顯示出來,例如: ```python >>> parser = argparse.ArgumentParser(prog='frobble') >>> parser.add_argument('--foo', action='store_true', ... help='foo the bars before frobbling') >>> parser.add_argument('bar', nargs='+', ... help='one of the bars to be frobbled') >>> parser.parse_args(['-h']) usage: frobble [-h] [--foo] bar [bar ...] positional arguments: bar one of the bars to be frobbled optional arguments: -h, --help show this help message and exit --foo foo the bars before frobbling ``` 當然,**關鍵字help**也支援格式化顯示,```%(prog)s```和大部分**add_argument()**的關鍵字,包括```%(default)s```,```%(type)s```,等等,例如: ```python >>> parser = argparse.ArgumentParser(prog='frobble') >>> parser.add_argument('bar', nargs='?', type=int, default=42, ... help='the bar to %(prog)s (default: %(default)s)') >>> parser.print_help() usage: frobble [-h] [bar] positional arguments: bar the bar to frobble (default: 42) optional arguments: -h, --help show this help message and exit ``` 格式為```%(keyword)s```,如果需要顯示```%```,就需要使用```%%``` 還存在一種特殊情況,假設我們不希望引數顯示在*--help*中,我們可以用:**argparse.SUPPRESS**,例如: ```python >>> parser = argparse.ArgumentParser(prog='frobble') >>> parser.add_argument('--foo', help=argparse.SUPPRESS) >>> parser.print_help() usage: frobble [-h] optional arguments: -h, --help show this help message and exit ``` ### 關鍵字dest **argparse**會把解析的結果儲存成*解析結果物件*的屬性,但是,屬性名是什麼呢?例如,```parser.add_argument(’-f', '--foo')```,解析結果是儲存在屬性```f```中還是```foo```中?**關鍵字dest**就是用於定製屬性名的。 我們先了解預設情況下,屬性名是什麼? **對位置引數而言,關鍵字dest預設為第一個引數名**,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('bar') >>> parser.parse_args(['XXX']) Namespace(bar='XXX') ``` **對可選引數而言,關鍵字dest首選第一個出現的長引數名。如果沒有長引數,則選擇第一個短引數名。不管選擇的是長引數還是短引數,都會把```-|---```給去掉,同時把名字中的```-```符號替換為```_```,以符合python的變數命名規則**,例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('-f', '--foo-bar', '--foo') >>> parser.add_argument('-x', '-y') >>> parser.parse_args('-f 1 -x 2'.split()) Namespace(foo_bar='1', x='2') >>> parser.parse_args('--foo 1 -y 2'.split()) Namespace(foo_bar='1', x='2') ``` 我們再看看,如果定製屬性名有什麼效果? ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', dest='bar') >>> parser.parse_args('--foo XXX'.split()) Namespace(bar='XXX') ``` ### 關鍵字metavar 在執行```-h|--help```,顯示的幫助資訊中,如何定製選項帶的引數名呢?例如: ``` -t T loop times ``` 我希望修改顯示的```T```為```TIMES```,更直觀。這時候我們就可以使用**關鍵字metavar**了。 在預設情況下,對**位置引數**,則會直接顯示引數名,對**可選引數**,則會轉為大寫。例如: ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo') >>> parser.add_argument('bar') >>> parser.parse_args('X --foo Y'.split()) Namespace(bar='X', foo='Y') >>> parser.print_help() usage: [-h] [--foo FOO] bar positional arguments: bar optional arguments: -h, --help show this help message and exit --foo FOO ``` 上例中,**位置引數bar**直接顯示為*bar*,而**可選引數--foo**帶的引數名就轉大寫顯示*FOO*。 如果我們定製顯示的引數名,該怎麼做呢? ```python >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', metavar='YYY') >>> parser.add_argument('bar', metavar='XXX') >>> parser.parse_args('X --foo Y'.split()) Namespace(bar='X', foo='Y') >>> parser.print_help() usage: [-h] [--foo YYY] XXX positional arguments: XXX optional arguments: -h, --help show this help message and exit --foo YYY ``` 當然,還存在一種特殊情況,就是有多個引數```nargs=N```,這時候**關鍵字metavar**可以以列表形式提供啦,例如: ```python >>> parser = argparse.ArgumentParser(prog='PROG') >>> parser.add_argument('-x', nargs=2) >>> parser.add_argument('--foo', nargs=2, metavar=('bar', 'baz')) >>> parser.print_help() usage: PROG [-h] [-x X X] [--foo bar baz] optional arguments: -h, --help show this help message and exit -x X X --foo bar baz ``` 最後,有一點要注意的時,**關鍵字metavar**與**關鍵字dest**不一樣的地方在於,**關鍵字metavar僅僅只影響-h|--help的顯示效果,關鍵dest則同時影響解析結果屬性名** ## 獲取解析結果 在[*action='store'*](#store)中提到:**選項名成為了解析結果物件的成員,而選項對應的值則成了成員的值**,所以如果我們需要獲取解析後的結果,直接使用解析結果的成員值就好了。例如: ```python >>> parser = argparse.ArgumentParser(prog='PROG') >>> parser.add_argument('-x', dest='xyz') >>> parser.add_argument('--foo', nargs=2, metavar=('bar', 'baz')) >>> args = parser.parse_args("--foo a b -x c".split()) >>> print(args.foo) >>> ['a', 'b'] >>> print(args.xyz) >>> c ```