argparse --- 命令列選項、引數和子命令的剖析器¶
在 3.2 版被加入.
原始碼:Lib/argparse.py
備註
雖然 argparse 是實作基本命令列應用程式時預設推薦的標準函式庫模組,但如果開發者對命令列應用程式的行為有更精確的要求,可能會發現它無法提供足夠的控制程度。當 argparse 不支援應用程式所需的行為時(例如完全停用交錯選項與位置引數的支援,或是允許以 - 開頭但可能與其他已定義選項相同的選項參數值),請參閱選擇一個命令列參數剖析函式庫以了解替代方案。
argparse 模組使得撰寫使用者友善的命令列介面變得容易。程式定義它需要什麼引數,而 argparse 會找出如何從 sys.argv 中剖析這些引數。argparse 模組也會自動產生說明和用法訊息。當使用者向程式提供無效引數時,此模組也會發出錯誤。
argparse 模組對命令列介面的支援是圍繞 argparse.ArgumentParser 的實例建構的。它是引數規格的容器,並具有適用於整個剖析器的選項:
parser = argparse.ArgumentParser(
prog='ProgramName',
description='What the program does',
epilog='Text at the bottom of help')
ArgumentParser.add_argument() 方法會將個別的引數規格附加到剖析器。它支援位置引數、接受值的選項以及開關旗標::
parser.add_argument('filename') # 位置引數
parser.add_argument('-c', '--count') # 接收一個值的選項
parser.add_argument('-v', '--verbose',
action='store_true') # 開關旗標
ArgumentParser.parse_args() 方法會執行剖析器,並將擷取的資料放入一個 argparse.Namespace 物件中::
args = parser.parse_args()
print(args.filename, args.count, args.verbose)
備註
如果你在尋找如何將 optparse 程式碼升級到 argparse 的指南,請參閱升級 Optparse 程式碼。
ArgumentParser 物件¶
- class argparse.ArgumentParser(prog=None, usage=None, description=None, epilog=None, parents=[], formatter_class=argparse.HelpFormatter, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True, allow_abbrev=True, exit_on_error=True, *, suggest_on_error=False, color=True)¶
建立一個新的
ArgumentParser物件。所有參數都應該作為關鍵字引數傳入。每個參數在下面都有更詳細的描述,簡而言之它們是:prog - 程式的名稱(預設值:從
__main__模組屬性和sys.argv[0]產生)usage - 描述程式用法的字串(預設值:從新增到剖析器的引數產生)
description - 引數說明之前要顯示的文字(預設值:無文字)
epilog - 引數說明之後要顯示的文字(預設值:無文字)
parents - 一個
ArgumentParser物件的串列,其引數也應該被包含formatter_class - 用於自訂幫助說明輸出的類別
prefix_chars - 前綴可選引數的字元集合(預設值:'-')
fromfile_prefix_chars - 前綴檔案的字元集合,額外引數將從這些檔案中讀取(預設值:
None)argument_default - 引數的全域預設值(預設值:
None)conflict_handler - 解決衝突可選引數的策略(通常不需要)
add_help - 加入一個
-h/--help選項到剖析器(預設值:True)allow_abbrev - 允許長選項被縮寫,只要縮寫是無歧義的(預設值:
True)exit_on_error - 決定
ArgumentParser在發生錯誤時是否帶著錯誤資訊退出。(預設值:True)suggest_on_error - 啟用對拼錯的引數選擇和子剖析器名稱的建議(預設值:
False)color - 允許彩色輸出(預設值:
True)
在 3.5 版的變更: 新增 allow_abbrev 參數。
在 3.8 版的變更: 在之前的版本中,allow_abbrev 也會停用短旗標的分組,例如以
-vv表示-v -v。在 3.9 版的變更: 新增 exit_on_error 參數。
在 3.14 版的變更: 新增 suggest_on_error 和 color 參數。
以下各節描述了這些參數的使用方式。
prog¶
預設情況下,ArgumentParser 會根據 Python 直譯器的執行方式計算要在說明訊息中顯示的程式名稱:
如果傳入的引數是一個檔案,則使用
sys.argv[0]的基底名稱。如果傳入的引數是一個目錄或 zip 檔案,則使用 Python 直譯器名稱加上
sys.argv[0]。如果使用了
-m選項,則使用 Python 直譯器名稱加上-m再加上模組或套件名稱。
這個預設值幾乎都不會錯,因為它會使說明訊息與命令列上呼叫程式時所用的字串一致。然而,若要更改此預設行為,可以使用 ArgumentParser 的 prog= 引數提供另一個值:
>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser.print_help()
usage: myprogram [-h]
options:
-h, --help show this help message and exit
請注意,無論程式名稱是從 sys.argv[0]、從 __main__ 模組屬性還是從 prog= 引數決定的,都可以在說明訊息中透過 %(prog)s 格式說明符號使用。
>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser.add_argument('--foo', help='foo of the %(prog)s program')
>>> parser.print_help()
usage: myprogram [-h] [--foo FOO]
options:
-h, --help show this help message and exit
--foo FOO foo of the myprogram program
在 3.14 版的變更: 預設的 prog 值現在會反映 __main__ 實際的執行方式,而非總是使用 os.path.basename(sys.argv[0])。
usage¶
預設情況下,ArgumentParser 會根據它包含的引數計算出用法訊息。可以使用 usage= 關鍵字引數覆寫預設訊息:
>>> parser = argparse.ArgumentParser(prog='PROG', usage='%(prog)s [options]')
>>> parser.add_argument('--foo', nargs='?', help='foo help')
>>> parser.add_argument('bar', nargs='+', help='bar help')
>>> parser.print_help()
usage: PROG [options]
positional arguments:
bar bar help
options:
-h, --help show this help message and exit
--foo [FOO] foo help
%(prog)s 格式說明符號可用於在你的用法訊息中填入程式名稱。
當為主剖析器指定了自訂用法訊息時,你可能也會想考慮將 prog 引數傳給 add_subparsers(),或是將 prog 和 usage 引數傳給 add_parser() 以確保子剖析器之間的命令前綴和用法資訊一致。
description¶
大多數對 ArgumentParser 建構函式的呼叫會使用 description= 關鍵字引數。此引數提供程式功能和運作方式的簡短描述。在說明訊息中,這個描述會顯示在命令列用法字串和各引數的說明訊息之間。
預設情況下,該描述會被自動斷行來配合給定的空間。若要更改此行為,請參閱 formatter_class 引數。
epilog¶
有些程式喜歡在引數描述之後顯示程式的額外說明。可以使用 ArgumentParser 的 epilog= 引數來指定這類文字:
>>> parser = argparse.ArgumentParser(
... description='A foo that bars',
... epilog="And that's how you'd foo a bar")
>>> parser.print_help()
usage: argparse.py [-h]
A foo that bars
options:
-h, --help show this help message and exit
And that's how you'd foo a bar
與 description 引數一樣,epilog= 文字預設會被自動斷行,但可以透過 ArgumentParser 的 formatter_class 引數調整此行為。
parents¶
有時候多個剖析器會共用一組共同的引數。與其重複定義這些引數,不如使用一個包含所有共用引數的剖析器,並將其傳給 ArgumentParser 的 parents= 引數。parents= 引數接受一個 ArgumentParser 物件的串列,收集它們的所有位置 action 和可選 action,並將這些 action 加入正在建構的 ArgumentParser 物件中:
>>> parent_parser = argparse.ArgumentParser(add_help=False)
>>> parent_parser.add_argument('--parent', type=int)
>>> foo_parser = argparse.ArgumentParser(parents=[parent_parser])
>>> foo_parser.add_argument('foo')
>>> foo_parser.parse_args(['--parent', '2', 'XXX'])
Namespace(foo='XXX', parent=2)
>>> bar_parser = argparse.ArgumentParser(parents=[parent_parser])
>>> bar_parser.add_argument('--bar')
>>> bar_parser.parse_args(['--bar', 'YYY'])
Namespace(bar='YYY', parent=None)
請注意,大多數父剖析器會指定 add_help=False。否則 ArgumentParser 會看到兩個 -h/--help 選項(一個在父剖析器中,一個在子剖析器中)並引發錯誤。
備註
你必須在透過 parents= 傳入剖析器之前完全初始化它們。如果你在子剖析器之後更改父剖析器,那些更改將不會反映在子剖析器中。
formatter_class¶
ArgumentParser 物件允許透過指定替代的格式化類別來自訂說明格式。目前有四個這樣的類別:
- class argparse.RawDescriptionHelpFormatter¶
- class argparse.RawTextHelpFormatter¶
- class argparse.ArgumentDefaultsHelpFormatter¶
- class argparse.MetavarTypeHelpFormatter¶
RawDescriptionHelpFormatter 和 RawTextHelpFormatter 提供了對文字描述顯示方式的更多控制。預設情況下,ArgumentParser 物件會在命令列說明訊息中為 description 和 epilog 文字自動斷行:
>>> parser = argparse.ArgumentParser(
... prog='PROG',
... description='''this description
... was indented weird
... but that is okay''',
... epilog='''
... likewise for this epilog whose whitespace will
... be cleaned up and whose words will be wrapped
... across a couple lines''')
>>> parser.print_help()
usage: PROG [-h]
this description was indented weird but that is okay
options:
-h, --help show this help message and exit
likewise for this epilog whose whitespace will be cleaned up and whose words
will be wrapped across a couple lines
將 RawDescriptionHelpFormatter 作為 formatter_class= 傳入,表示 description 和 epilog 已經正確格式化,不應自動斷行:
>>> parser = argparse.ArgumentParser(
... prog='PROG',
... formatter_class=argparse.RawDescriptionHelpFormatter,
... description=textwrap.dedent('''\
... Please do not mess up this text!
... --------------------------------
... I have indented it
... exactly the way
... I want it
... '''))
>>> parser.print_help()
usage: PROG [-h]
Please do not mess up this text!
--------------------------------
I have indented it
exactly the way
I want it
options:
-h, --help show this help message and exit
RawTextHelpFormatter 會為所有種類的說明文字保留空白,包括引數描述。然而多個換行符號會被替換為一個。如果你希望保留多個空白行,請在換行符號之間加入空格。
ArgumentDefaultsHelpFormatter 會自動將預設值的資訊加入每個引數的說明訊息中:
>>> parser = argparse.ArgumentParser(
... prog='PROG',
... formatter_class=argparse.ArgumentDefaultsHelpFormatter)
>>> parser.add_argument('--foo', type=int, default=42, help='FOO!')
>>> parser.add_argument('bar', nargs='*', default=[1, 2, 3], help='BAR!')
>>> parser.print_help()
usage: PROG [-h] [--foo FOO] [bar ...]
positional arguments:
bar BAR! (default: [1, 2, 3])
options:
-h, --help show this help message and exit
--foo FOO FOO! (default: 42)
MetavarTypeHelpFormatter 使用每個引數的 type 引數名稱作為其值的顯示名稱(而非像一般格式化器使用 dest):
>>> parser = argparse.ArgumentParser(
... prog='PROG',
... formatter_class=argparse.MetavarTypeHelpFormatter)
>>> parser.add_argument('--foo', type=int)
>>> parser.add_argument('bar', type=float)
>>> parser.print_help()
usage: PROG [-h] [--foo int] float
positional arguments:
float
options:
-h, --help show this help message and exit
--foo int
prefix_chars¶
大多數命令列選項會使用 - 作為前綴,例如 -f/--foo。需要支援不同或額外前綴字元的剖析器,例如 +f 或 /foo 之類的選項,可以使用 ArgumentParser 建構函式的 prefix_chars= 引數來指定:
>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+')
>>> parser.add_argument('+f')
>>> parser.add_argument('++bar')
>>> parser.parse_args('+f X ++bar Y'.split())
Namespace(bar='Y', f='X')
prefix_chars= 引數預設值為 '-'。提供一個不包含 - 的字元集合會導致 -f/--foo 選項被禁止。
fromfile_prefix_chars¶
當處理特別長的引數串列時,有時候將引數串列保存在檔案中可能比在命令列上逐一輸入更合理。如果將 fromfile_prefix_chars= 引數傳給 ArgumentParser 建構函式,那麼剖析器會將以任何指定字元開頭的引數視為檔案,並以檔案包含的引數取代之。例如:
>>> with open('args.txt', 'w', encoding=sys.getfilesystemencoding()) as fp:
... fp.write('-f\nbar')
...
>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
>>> parser.add_argument('-f')
>>> parser.parse_args(['-f', 'foo', '@args.txt'])
Namespace(f='bar')
從檔案讀取的引數預設必須每行一個(但也請參閱 convert_arg_line_to_args()),且剖析器會將其視為與命令列上引用檔案的原始引數位於相同位置。因此在上面的範例中,運算式 ['-f', 'foo', '@args.txt'] 等同於運算式 ['-f', 'foo', '-f', 'bar']。
備註
空行會被視為空字串 (''),可以作為值但不能作為引數。若空行被讀取為引數,會導致 "unrecognized arguments" 錯誤。
ArgumentParser 使用檔案系統編碼和錯誤處理函式來讀取包含引數的檔案。
fromfile_prefix_chars= 引數預設值為 None,意味著引數永遠不會被視為檔案參照。
在 3.12 版的變更: ArgumentParser 將讀取引數檔案的編碼和錯誤處理從預設值(例如 locale.getpreferredencoding(False) 和 "strict")改為檔案系統編碼和錯誤處理函式。在 Windows 上引數檔案應使用 UTF-8 而非 ANSI 字碼頁編碼。
argument_default¶
一般而言,引數預設值可以透過將預設值傳給 add_argument() 或是透過呼叫 set_defaults() 方法並指定一組名稱—值對 (name-value pair) 來設定。然而有時候為引數指定一個剖析器層級的單一預設值可能很有用。這可以透過將 argument_default= 關鍵字引數傳給 ArgumentParser 來完成。例如若要全域地抑制 parse_args() 呼叫時的屬性建立,我們可以提供 argument_default=SUPPRESS:
>>> parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
>>> parser.add_argument('--foo')
>>> parser.add_argument('bar', nargs='?')
>>> parser.parse_args(['--foo', '1', 'BAR'])
Namespace(bar='BAR', foo='1')
>>> parser.parse_args([])
Namespace()
allow_abbrev¶
當你將引數串列傳給 ArgumentParser 的 parse_args() 方法時,它會通常會辨識為長選項的縮寫。
可以透過將 allow_abbrev 設為 False 來停用此功能:
>>> parser = argparse.ArgumentParser(prog='PROG', allow_abbrev=False)
>>> parser.add_argument('--foobar', action='store_true')
>>> parser.add_argument('--foonley', action='store_false')
>>> parser.parse_args(['--foon'])
usage: PROG [-h] [--foobar] [--foonley]
PROG: error: unrecognized arguments: --foon
在 3.5 版被加入.
conflict_handler¶
ArgumentParser 物件不允許兩個 action 擁有相同的選項字串。預設情況下,如果嘗試建立一個使用已存在選項字串的引數,ArgumentParser 物件會引發例外:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-f', '--foo', help='old foo help')
>>> parser.add_argument('--foo', help='new foo help')
Traceback (most recent call last):
..
ArgumentError: argument --foo: conflicting option string(s): --foo
有時候(例如使用 parents 時)直接覆寫具有相同選項字串的舊引數可能很有用。若要得到此行為,可以將值 'resolve' 提供給 ArgumentParser 的 conflict_handler= 引數:
>>> parser = argparse.ArgumentParser(prog='PROG', conflict_handler='resolve')
>>> parser.add_argument('-f', '--foo', help='old foo help')
>>> parser.add_argument('--foo', help='new foo help')
>>> parser.print_help()
usage: PROG [-h] [-f FOO] [--foo FOO]
options:
-h, --help show this help message and exit
-f FOO old foo help
--foo FOO new foo help
請注意,只有當一個 action 的所有選項字串都被覆寫時,ArgumentParser 物件才會移除該 action。因此在上面的範例中,舊的 -f/--foo action 會保留為 -f action,因為只有 --foo 選項字串被覆寫。
add_help¶
預設情況下,ArgumentParser 物件會加入一個選項來簡單地顯示剖析器的說明訊息。如果在命令列上提供了 -h 或 --help,將會印出 ArgumentParser 的說明。
停用自動加入的幫助說明選項 (help option) 有時可能很有用。可以透過將 False 作為 add_help= 引數傳給 ArgumentParser 來達成:
>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)
>>> parser.add_argument('--foo', help='foo help')
>>> parser.print_help()
usage: PROG [--foo FOO]
options:
--foo FOO foo help
幫助說明選項通常是 -h/--help。例外情況是如果指定了 prefix_chars= 且不包含 -,此時 -h 和 --help 不是有效的選項。在這種情況下,prefix_chars 中的第一個字元會用作幫助說明選項的前綴:
>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='+/')
>>> parser.print_help()
usage: PROG [+h]
options:
+h, ++help show this help message and exit
exit_on_error¶
當你將無效的引數串列傳給 ArgumentParser 的 parse_args() 方法時,它通常會向 sys.stderr 印出一個訊息並以狀態碼 2 退出。
如果使用者想要手動捕捉錯誤,可以透過將 exit_on_error 設為 False 來啟用此功能:
>>> parser = argparse.ArgumentParser(exit_on_error=False)
>>> parser.add_argument('--integers', type=int)
_StoreAction(option_strings=['--integers'], dest='integers', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)
>>> try:
... parser.parse_args('--integers a'.split())
... except argparse.ArgumentError:
... print('Catching an argumentError')
...
Catching an argumentError
在 3.9 版被加入.
suggest_on_error¶
預設情況下,當使用者傳入無效的引數選擇或子剖析器名稱時,ArgumentParser 會帶著錯誤資訊退出,並將允許的引數選擇(如果有指定的話)或子剖析器名稱列為錯誤訊息的一部分。
如果使用者想要啟用對拼錯的引數選擇和子剖析器名稱的建議,可以透過將 suggest_on_error 設為 True 來啟用此功能。請注意,這僅適用於指定的選擇皆為字串的引數:
>>> parser = argparse.ArgumentParser(description='Process some integers.',
suggest_on_error=True)
>>> parser.add_argument('--action', choices=['sum', 'max'])
>>> parser.add_argument('integers', metavar='N', type=int, nargs='+',
... help='an integer for the accumulator')
>>> parser.parse_args(['--action', 'sumn', 1, 2, 3])
tester.py: error: argument --action: invalid choice: 'sumn', maybe you meant 'sum'? (choose from 'sum', 'max')
如果你正在撰寫需要與舊版 Python 相容的程式碼,並且想要在 suggest_on_error 可用時伺機使用它,你可以在初始化剖析器後將其設為屬性,而非使用關鍵字引數:
>>> parser = argparse.ArgumentParser(description='Process some integers.')
>>> parser.suggest_on_error = True
在 3.14 版被加入.
color¶
預設情況下,說明訊息會使用 ANSI 跳脫序列以彩色印出。如果你想要純文字說明訊息,可以在你的本地環境中停用它,或是透過將 color 設為 False 在引數剖析器本身停用:
>>> parser = argparse.ArgumentParser(description='Process some integers.',
... color=False)
>>> parser.add_argument('--action', choices=['sum', 'max'])
>>> parser.add_argument('integers', metavar='N', type=int, nargs='+',
... help='an integer for the accumulator')
>>> parser.parse_args(['--help'])
請注意,當 color=True 時,彩色輸出取決於環境變數和終端機能力。然而,如果 color=False,即使設定了 FORCE_COLOR 之類的環境變數,彩色輸出也是會被停用。
備註
將 stderr 重新導向到檔案時,錯誤訊息會包含顏色代碼。若要避免此情況,請設定 NO_COLOR 或 PYTHON_COLORS 環境變數(例如 NO_COLOR=1 python script.py 2> errors.txt)。
在 3.14 版被加入.
add_argument() 方法¶
- ArgumentParser.add_argument(name or flags..., *[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest][, deprecated])¶
定義單個命令列引數應如何被剖析。每個參數在下面都有更詳細的描述,簡而言之它們是:
name or flags - 一個名稱或選項字串的串列,例如
'foo'或'-f', '--foo'。action - 在命令列遇到此引數時要執行的基本 action 類型。
nargs - 應消耗的命令列引數數量。
default - 如果引數不在命令列中且不在命名空間物件中時所產生的值。
type - 命令列引數應轉換成的型別。
choices - 引數允許值的序列。
required - 命令列選項是否可省略(僅限可選引數)。
help - 引數功能的簡短描述。
metavar - 引數在用法訊息中的名稱。
dest - 要加入到
parse_args()回傳物件中的屬性名稱。deprecated - 引數的使用是否已被棄用。
以下各節描述了這些參數的使用方式。
name or flags¶
add_argument() 方法必須知道預期的是可選引數(如 -f 或 --foo)還是位置引數(如檔案名稱的串列)。因此,傳給 add_argument() 的第一個引數必須是一系列旗標或一個簡單的引數名稱。
例如,可選引數可以像這樣建立:
>>> parser.add_argument('-f', '--foo')
而位置引數可以像這樣建立:
>>> parser.add_argument('bar')
當呼叫 parse_args() 時,可選引數會透過 - 前綴來辨識,其餘的引數則假設為位置引數:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-f', '--foo')
>>> parser.add_argument('bar')
>>> parser.parse_args(['BAR'])
Namespace(bar='BAR', foo=None)
>>> parser.parse_args(['BAR', '--foo', 'FOO'])
Namespace(bar='BAR', foo='FOO')
>>> parser.parse_args(['--foo', 'FOO'])
usage: PROG [-h] [-f FOO] bar
PROG: error: the following arguments are required: bar
預設情況下,argparse 會自動處理引數的內部命名和顯示名稱,簡化流程而不需要額外設定。因此,你不需要指定 dest 和 metavar 參數。dest 參數預設為引數名稱,以底線 _ 取代連字號 -。metavar 參數預設為大寫的名稱。例如:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo-bar')
>>> parser.parse_args(['--foo-bar', 'FOO-BAR'])
Namespace(foo_bar='FOO-BAR')
>>> parser.print_help()
usage: [-h] [--foo-bar FOO-BAR]
optional arguments:
-h, --help show this help message and exit
--foo-bar FOO-BAR
action¶
ArgumentParser 物件會將命令列引數與 action 關聯起來。這些 action 幾乎可以對與其關聯的命令列引數做任何事情,但大多數 action 只是將屬性加入到 parse_args() 回傳的物件中。action 關鍵字引數指定命令列引數應如何被處理。提供的 action 有:
'store'- 這只是儲存引數的值。這是預設的 action。'store_const'- 這會儲存 const 關鍵字引數指定的值;請注意 const 關鍵字引數預設為None。'store_const'action 最常與指定某種旗標的可選引數一起使用。例如:>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action='store_const', const=42) >>> parser.parse_args(['--foo']) Namespace(foo=42)
'store_true'和'store_false'- 這些是'store_const'的特殊情況,分別儲存值True和False,預設值為False和True:>>> 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)
'append'- 這會將每個引數值附加到一個串列中。這對於允許一個選項被多次指定很有用。如果預設值是一個非空的串列,剖析後的值會以預設串列的元素開始,命令列的任何值則會附加在那些預設值之後。使用範例:>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action='append', default=['0']) >>> parser.parse_args('--foo 1 --foo 2'.split()) Namespace(foo=['0', '1', '2'])
'append_const'- 這會將 const 關鍵字引數指定的值附加到一個串列中;請注意 const 關鍵字引數預設為None。'append_const'action 通常在多個引數需要將常數儲存到同一個串列時很有用。例如:>>> 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=[<class 'str'>, <class 'int'>])
'extend'- 這會將多值引數的每個項目附加到一個串列中。'extend'action 通常與 nargs 關鍵字引數值'+'或'*'一起使用。請注意,當 nargs 為None(預設值)或'?'時,引數字串的每個字元都會被附加到串列中。使用範例:>>> parser = argparse.ArgumentParser() >>> parser.add_argument("--foo", action="extend", nargs="+", type=str) >>> parser.parse_args(["--foo", "f1", "--foo", "f2", "f3", "f4"]) Namespace(foo=['f1', 'f2', 'f3', 'f4'])
在 3.8 版被加入.
'count'- 這會計算引數出現的次數。例如,這對於增加詳細程度等級很有用:>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--verbose', '-v', action='count', default=0) >>> parser.parse_args(['-vvv']) Namespace(verbose=3)
請注意,除非明確設為 0,否則 default 將為
None。'help'- 這會印出目前剖析器中所有選項的完整說明訊息,然後退出。預設情況下,help action 會自動加入到剖析器。有關輸出如何建立的詳情,請參閱ArgumentParser。'version'- 這預期在add_argument()呼叫中有一個version=關鍵字引數,並在被呼叫時印出版本資訊並退出:>>> 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
你也可以傳遞一個 Action 子類別(例如 BooleanOptionalAction)或實作相同介面的其他物件。只有會消耗命令列引數的 action(例如 'store'、'append'、'extend' 或 nargs 不為零的自訂 action)可用於位置引數。
建立自訂 action 的建議方式是擴充 Action,覆寫 __call__() 方法,並選擇性地覆寫 __init__() 和 format_usage() 方法。你也可以使用 register() 方法註冊自訂 action,並透過它們的註冊名稱來參照。
自訂 action 的範例:
>>> class FooAction(argparse.Action):
... def __init__(self, option_strings, dest, nargs=None, **kwargs):
... if nargs is not None:
... raise ValueError("nargs not allowed")
... super().__init__(option_strings, dest, **kwargs)
... def __call__(self, parser, namespace, values, option_string=None):
... print('%r %r %r' % (namespace, values, option_string))
... setattr(namespace, self.dest, values)
...
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action=FooAction)
>>> parser.add_argument('bar', action=FooAction)
>>> args = parser.parse_args('1 --foo 2'.split())
Namespace(bar=None, foo=None) '1' None
Namespace(bar='1', foo=None) '2' '--foo'
>>> args
Namespace(bar='1', foo='2')
更多詳情請見 Action。
nargs¶
ArgumentParser 物件通常將單個命令列引數與單個要執行的 action 關聯起來。nargs 關鍵字引數會將不同數量的命令列引數與單個 action 關聯。另請參閱指定不明確的引數。支援的值有:
N(一個整數)。命令列中的N個引數會被收集到一個串列中。例如:>>> 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會產生一個只有一個項目的串列。這與預設情況不同,預設情況下項目會單獨產生。
'?'。如果可能的話,會從命令列消耗一個引數,並作為單個項目產生。如果沒有命令列引數存在,會產生 default 的值。請注意,對於可選引數有一個額外的情況 —— 選項字串存在但後面沒有跟著命令列引數,在這種情況下會產生 const 的值。以下是這個情況的範例:>>> 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')
nargs='?'比較常見的用途之一是允許可選的輸入和輸出檔案:>>> parser = argparse.ArgumentParser() >>> parser.add_argument('infile', nargs='?') >>> parser.add_argument('outfile', nargs='?') >>> parser.parse_args(['input.txt', 'output.txt']) Namespace(infile='input.txt', outfile='output.txt') >>> parser.parse_args(['input.txt']) Namespace(infile='input.txt', outfile=None) >>> parser.parse_args([]) Namespace(infile=None, outfile=None)
'*'。所有存在的命令列引數都會被收集到一個串列中。請注意,有多個nargs='*'的位置引數通常沒有太大意義,但多個nargs='*'的可選引數是可能的。例如:>>> 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'])
'+'。與'*'一樣,所有存在的命令列引數都會被收集到一個串列中。此外,如果沒有至少一個命令列引數存在就會產生一個錯誤訊息。例如:>>> 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
如果未提供 nargs 關鍵字引數,消耗的引數數量由 action 決定。一般而言,這意味著會消耗單個命令列引數並產生單個項目(而非串列)。不消耗命令列引數的 action(例如 'store_const')會設定 nargs=0。
const¶
add_argument() 的 const 引數用於保存不從命令列讀取但為各種 ArgumentParser action 所需的常數值。它最常見的兩種用途是:
當
add_argument()以action='store_const'或action='append_const'呼叫時。這些 action 會將const值加入到parse_args()回傳物件的其中一個屬性中。範例請參閱 action 描述。如果未向add_argument()提供const,它會接收預設值None。當
add_argument()以選項字串(如-f或--foo)和nargs='?'呼叫時。這會建立一個可選引數,後面可以跟著零個或一個命令列引數。剖析命令列時,如果遇到選項字串但後面沒有命令列引數,會使用const的值。範例請參閱 nargs 描述。
在 3.11 版的變更: const=None 為預設值,包括當 action='append_const' 或 action='store_const' 時。
default¶
所有可選引數和部分位置引數都可以在命令列上被省略。add_argument() 的 default 關鍵字引數(其值預設為 None)指定在命令列引數不存在時應使用的值。對於可選引數,當選項字串不在命令列上時會使用 default 值:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default=42)
>>> parser.parse_args(['--foo', '2'])
Namespace(foo='2')
>>> parser.parse_args([])
Namespace(foo=42)
如果目標命名空間已經設定了一個屬性,action 的 default 不會覆寫它:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default=42)
>>> parser.parse_args([], namespace=argparse.Namespace(foo=101))
Namespace(foo=101)
如果 default 值是一個字串,剖析器會像剖析命令列引數一樣剖析該值。特別是如果有提供 type 轉換引數,剖析器會在設定 Namespace 回傳值的屬性之前先套用它。否則剖析器會直接使用該值:
>>> 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 等於 ? 或 * 的位置引數,當沒有命令列引數存在時會使用 default 值:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('foo', nargs='?', default=42)
>>> parser.parse_args(['a'])
Namespace(foo='a')
>>> parser.parse_args([])
Namespace(foo=42)
對於 required 引數,default 值會被忽略。例如,這適用於 nargs 值不是 ? 或 * 的位置引數,或是標記為 required=True 的可選引數。
若有提供 default=argparse.SUPPRESS,命令列引數不存在時就不會加入任何屬性:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default=argparse.SUPPRESS)
>>> parser.parse_args([])
Namespace()
>>> parser.parse_args(['--foo', '1'])
Namespace(foo='1')
type¶
預設情況下,剖析器將命令列引數作為簡單字串讀取。然而命令列字串往往應直譯為另一種型別,例如 float 或 int。add_argument() 的 type 關鍵字允許執行任何必要的型別檢查和型別轉換。
如果 type 關鍵字與 default 關鍵字一起使用,型別轉換器只會在預設值為字串時套用。
type 的引數可以是一個接受單個字串的可呼叫物件,或是已註冊型別的名稱(請參閱 register())。如果函式引發 ArgumentTypeError、TypeError 或 ValueError,剖析器會捕捉例外並顯示格式良好的錯誤訊息。其他例外型別則不處理。
常見的內建型別和函式可以作為型別轉換器使用:
import argparse
import pathlib
parser = argparse.ArgumentParser()
parser.add_argument('count', type=int)
parser.add_argument('distance', type=float)
parser.add_argument('street', type=ascii)
parser.add_argument('code_point', type=ord)
parser.add_argument('datapath', type=pathlib.Path)
也可以用那些使用者定義的函式:
>>> def hyphenated(string):
... return '-'.join([word[:4] for word in string.casefold().split()])
...
>>> parser = argparse.ArgumentParser()
>>> _ = parser.add_argument('short_title', type=hyphenated)
>>> parser.parse_args(['"The Tale of Two Cities"'])
Namespace(short_title='"the-tale-of-two-citi')
不建議使用 bool() 函式作為型別轉換器。它所做的只是將空字串轉為 False,將非空字串轉為 True。這通常不是期望的行為。
一般而言,type 關鍵字是一個便利功能,應只用於只會引發三種支援的例外之一的簡單轉換。任何更複雜的錯誤處理或資源管理都應在引數剖析之後的下游進行。
例如,JSON 或 YAML 轉換具有複雜的錯誤情況,需要比 type 關鍵字所能提供的更好的報告。JSONDecodeError 無法得到良好的格式化,而 FileNotFoundError 例外則完全不會處理。
即使是 FileType 在與 type 關鍵字一起使用時也有其限制。如果一個引數使用了 FileType,然後後續的引數失敗了,雖然會報告錯誤但檔案不會自動關閉。在這種情況下,最好等到剖析器執行完畢後,再使用 with 陳述式來管理檔案。
對於僅檢查固定值集合的型別檢查器,請考慮改用 choices 關鍵字。
choices¶
某些命令列引數應從一組受限的值中選擇。這可以透過將序列物件作為 choices 關鍵字引數傳給 add_argument() 來處理。剖析命令列時會檢查引數值,如果引數不是可接受的值之一,就會顯示錯誤訊息:
>>> 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')
任何序列都可以作為 choices 值傳入,因此 list 物件、tuple 物件和自訂序列都有被支援。
不建議使用 enum.Enum,因為很難控制它在用法、說明和錯誤訊息中的長相。
請注意,choices 是在任何 type 轉換執行之後才被檢查的,因此 choices 中的物件應符合指定的 type。這可能使 choices 在用法、說明或錯誤訊息中的長相看起來不尋常。
若要保持 choices 對使用者友善,請考慮使用自訂型別包裝器來轉換和格式化值,或是省略 type 並在你的應用程式碼中處理轉換。
格式化的選擇會覆寫通常從 dest 衍生的預設 metavar。這通常是你想要的,因為使用者永遠看不到 dest 參數。如果此顯示不理想(也許因為有很多選擇),只需指定一個明確的 metavar。
required¶
一般而言,argparse 模組假定像 -f 和 --bar 這樣的旗標表示可選引數,它們總是可以在命令列上被省略。若要使一個選項成為必要的,可以為 add_argument() 的 required= 關鍵字引數指定 True:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', required=True)
>>> parser.parse_args(['--foo', 'BAR'])
Namespace(foo='BAR')
>>> parser.parse_args([])
usage: [-h] --foo FOO
: error: the following arguments are required: --foo
如範例所示,如果一個選項被標記為 required,parse_args() 會在該選項不在命令列上時報告錯誤。
備註
必要選項一般認為是不良做法,因為使用者期望選項是可選的,因此應盡可能避免使用。
help¶
help 值是一個包含引數簡短描述的字串。當使用者請求說明(通常是在命令列上使用 -h 或 --help)時,這些 help 描述會與每個引數一起顯示。
help 字串可以包含各種格式說明符號以避免重複程式名稱或引數 default 之類的內容。可用的說明符號包括程式名稱 %(prog)s 以及 add_argument() 的大多數關鍵字引數,例如 %(default)s、%(type)s 等:
>>> 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)
options:
-h, --help show this help message and exit
由於 help 字串支援 %-格式化,如果你想讓文字 % 出現在 help 字串中,你必須將它跳脫為 %%。
argparse 支援透過將 help 值設為 argparse.SUPPRESS 來隱藏某些選項的說明條目:
>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('--foo', help=argparse.SUPPRESS)
>>> parser.print_help()
usage: frobble [-h]
options:
-h, --help show this help message and exit
metavar¶
當 ArgumentParser 產生說明訊息時,它需要某種方式來指稱每個預期的引數。預設情況下,ArgumentParser 物件使用 dest 值作為每個物件的「名稱」。對於位置引數動作,預設直接使用 dest 值;對於可選引數動作,則將 dest 值轉為大寫。因此,一個 dest='bar' 的位置引數稱為 bar。一個應後接單一命令列引數的 --foo 可選引數稱為 FOO。範例:
>>> 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
options:
-h, --help show this help message and exit
--foo FOO
可以用 metavar 指定替代名稱:
>>> 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
options:
-h, --help show this help message and exit
--foo YYY
請注意 metavar 只會更改顯示的名稱——parse_args() 物件上的屬性名稱仍由 dest 值決定。
不同的 nargs 值可能導致 metavar 被多次使用。提供一個元組給 metavar 可以為每個引數指定不同的顯示:
>>> 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]
options:
-h, --help show this help message and exit
-x X X
--foo bar baz
dest¶
大多數 ArgumentParser action 會將某個值作為 parse_args() 回傳物件的屬性加入。此屬性的名稱由 add_argument() 的 dest 關鍵字引數決定。對於位置引數 action,dest 通常作為 add_argument() 的第一個引數提供:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('bar')
>>> parser.parse_args(['XXX'])
Namespace(bar='XXX')
對於可選引數 action,dest 的值通常從選項字串推斷。ArgumentParser 透過取第一個長選項字串並去除開頭的 -- 字串來產生 dest 的值。如果沒有提供長選項字串,dest 會從第一個短選項字串去除開頭的 - 字元來衍生。任何內部的 - 字元都會轉為 _ 字元,以確保該字串是有效的屬性名稱。以下範例說明了此行為:
>>> 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')
dest 允許提供自訂的屬性名稱:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', dest='bar')
>>> parser.parse_args('--foo XXX'.split())
Namespace(bar='XXX')
deprecated¶
在專案的生命週期中,某些引數可能需要從命令列移除。在移除它們之前,你應告知使用者這些引數已棄用且即將移除。add_argument() 的 deprecated 關鍵字引數(預設為 False)指定引數是否已棄用並將在未來移除。對於引數,如果 deprecated 為 True,那麼使用該引數時會向 sys.stderr 印出警告:
>>> import argparse
>>> parser = argparse.ArgumentParser(prog='snake.py')
>>> parser.add_argument('--legs', default=0, type=int, deprecated=True)
>>> parser.parse_args([])
Namespace(legs=0)
>>> parser.parse_args(['--legs', '4'])
snake.py: warning: option '--legs' is deprecated
Namespace(legs=4)
在 3.13 版被加入.
Action 類別¶
Action 類別實作了 Action API,為一個可呼叫物件,會回傳能夠處理來自命令列引數的可呼叫物件。任何遵循此 API 的物件都可以作為 action 參數傳給 add_argument()。
- class argparse.Action(option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, metavar=None)¶
Action物件被ArgumentParser用來表示從命令列的一個或多個字串中剖析單個引數所需的資訊。Action類別必須接受兩個位置引數以及傳給ArgumentParser.add_argument()的任何關鍵字引數(除了action本身)。Action的實例(或任何傳給action參數的可呼叫物件的回傳值)應定義dest、option_strings、default、type、required、help等屬性。確保這些屬性被定義的最簡單方式是呼叫Action.__init__()。- __call__(parser, namespace, values, option_string=None)¶
Action實例應該是可呼叫的,因此子類別必須覆寫__call__()方法,它應接受四個參數:parser - 包含此 action 的
ArgumentParser物件。namespace - 將由
parse_args()回傳的Namespace物件。大多數 action 使用setattr()將屬性加入此物件。values - 相關聯的命令列引數,已套用任何型別轉換。型別轉換透過
add_argument()的 type 關鍵字引數指定。option_string - 用來呼叫此 action 的選項字串。
option_string引數是可選的,如果 action 與位置引數關聯則不會出現。
__call__()方法可以執行任意動作,但通常會根據dest和values在namespace上設定屬性。
- format_usage()¶
Action子類別可以定義一個format_usage()方法,它不接受引數並回傳一個字串,該字串會在印出程式用法時使用。如果未提供此方法,會使用合理的預設值。
- class argparse.BooleanOptionalAction¶
Action的子類別,用於處理具有正向和負向選項的布林旗標。加入像--foo這樣的單個引數會自動建立--foo和--no-foo選項,其分別儲存True和False:>>> import argparse >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action=argparse.BooleanOptionalAction) >>> parser.parse_args(['--no-foo']) Namespace(foo=False)
在 3.9 版被加入.
parse_args() 方法¶
- ArgumentParser.parse_args(args=None, namespace=None)¶
將引數字串轉換為物件並將它們指定為命名空間的屬性。回傳填充後的命名空間。
先前對
add_argument()的呼叫決定了確切建立什麼物件以及如何指定它們。詳情請參閱add_argument()的文件。
選項值語法¶
parse_args() 方法支援多種方式來指定選項的值(如果它接受值的話)。在最簡單的情況下,選項和它的值作為兩個獨立的引數傳入:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x')
>>> parser.add_argument('--foo')
>>> parser.parse_args(['-x', 'X'])
Namespace(foo=None, x='X')
>>> parser.parse_args(['--foo', 'FOO'])
Namespace(foo='FOO', x=None)
對於長選項(名稱長度超過一個字元的選項),選項和值也可以作為單個命令列引數傳入,使用 = 來分隔它們:
>>> parser.parse_args(['--foo=FOO'])
Namespace(foo='FOO', x=None)
對於短選項(只有一個字元長的選項),選項和它的值可以串接在一起:
>>> parser.parse_args(['-xX'])
Namespace(foo=None, x='X')
如果只有最後一個選項需要值(或都不需要),多個短選項就可以被合併在一起、只使用一個 - 前綴:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x', action='store_true')
>>> parser.add_argument('-y', action='store_true')
>>> parser.add_argument('-z')
>>> parser.parse_args(['-xyzZ'])
Namespace(x=True, y=True, z='Z')
無效引數¶
在剖析命令列時,parse_args() 會檢查各種錯誤,包括有歧義的選項、無效的型別、無效的選項、錯誤的位置引數數量等。當遇到此類錯誤時,它會退出並印出錯誤及用法訊息:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', type=int)
>>> parser.add_argument('bar', nargs='?')
>>> # 無效型別
>>> parser.parse_args(['--foo', 'spam'])
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: argument --foo: invalid int value: 'spam'
>>> # 無效選項
>>> parser.parse_args(['--bar'])
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: no such option: --bar
>>> # 錯誤引數數量
>>> parser.parse_args(['spam', 'badger'])
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: extra arguments found: badger
包含 - 的引數¶
parse_args() 方法嘗試在使用者明顯犯錯時給出錯誤,但有些情況本質上是有歧義的。例如命令列引數 -1 既可能是嘗試指定一個選項,也可能是嘗試提供一個位置引數。parse_args() 方法在此處很謹慎:位置引數只有在看起來像負數且剖析器中沒有看起來像負數的選項時,才可以用 - 開頭:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x')
>>> parser.add_argument('foo', nargs='?')
>>> # 沒有負數選項,所以 -1 是位置引數
>>> parser.parse_args(['-x', '-1'])
Namespace(foo=None, x='-1')
>>> # 沒有負數選項,所以 -1 和 -5 是位置引數
>>> parser.parse_args(['-x', '-1', '-5'])
Namespace(foo='-5', x='-1')
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-1', dest='one')
>>> parser.add_argument('foo', nargs='?')
>>> # 有負數選項存在,所以 -1 是選項
>>> parser.parse_args(['-1', 'X'])
Namespace(foo=None, one='X')
>>> # 有負數選項存在,所以 -2 是選項
>>> parser.parse_args(['-2'])
usage: PROG [-h] [-1 ONE] [foo]
PROG: error: no such option: -2
>>> # 有負數選項存在,所以兩個 -1 都是選項
>>> parser.parse_args(['-1', '-1'])
usage: PROG [-h] [-1 ONE] [foo]
PROG: error: argument -1: expected one argument
如果你有必須以 - 開頭且不像負數的位置引數,你可以插入偽引數 '--',它會告訴 parse_args() 在此之後的所有內容都是位置引數:
>>> parser.parse_args(['--', '-f'])
Namespace(foo='-f', one=None)
更多詳情請參閱 argparse howto 中關於有歧義引數的說明。
引數縮寫 (前綴匹配)¶
parse_args() 方法預設允許長選項被縮寫為前綴,只要縮寫是無歧義的(前綴匹配到唯一的選項):
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-bacon')
>>> parser.add_argument('-badger')
>>> parser.parse_args('-bac MMM'.split())
Namespace(bacon='MMM', badger=None)
>>> parser.parse_args('-bad WOOD'.split())
Namespace(bacon=None, badger='WOOD')
>>> parser.parse_args('-ba BA'.split())
usage: PROG [-h] [-bacon BACON] [-badger BADGER]
PROG: error: ambiguous option: -ba could match -badger, -bacon
對於可能產生多個選項的引數會產生錯誤。可以透過將 allow_abbrev 設為 False 來停用此功能。
sys.argv 之外¶
有時候讓 ArgumentParser 剖析 sys.argv 以外的引數可能很有用。這可以透過將字串串列傳給 parse_args() 來完成。這對於在互動式提示中測試很有用:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument(
... 'integers', metavar='int', type=int, choices=range(10),
... nargs='+', help='an integer in the range 0..9')
>>> parser.add_argument(
... '--sum', dest='accumulate', action='store_const', const=sum,
... default=max, help='sum the integers (default: find the max)')
>>> parser.parse_args(['1', '2', '3', '4'])
Namespace(accumulate=<built-in function max>, integers=[1, 2, 3, 4])
>>> parser.parse_args(['1', '2', '3', '4', '--sum'])
Namespace(accumulate=<built-in function sum>, integers=[1, 2, 3, 4])
命名空間物件¶
- class argparse.Namespace¶
parse_args()預設使用的簡單類別,用來建立保存屬性的物件並回傳它。這個類別刻意保持簡單,只是一個具有可讀字串表示的
object子類別。如果你偏好以類字典的方式檢視屬性,可以使用標準 Python 慣用寫法vars():>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo') >>> args = parser.parse_args(['--foo', 'BAR']) >>> vars(args) {'foo': 'BAR'}
讓
ArgumentParser將屬性指定給已存在的物件而非新的Namespace物件也可能很有用。這可以透過指定namespace=關鍵字引數來達成:>>> class C: ... pass ... >>> c = C() >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo') >>> parser.parse_args(args=['--foo', 'BAR'], namespace=c) >>> c.foo 'BAR'
其他工具¶
子命令¶
- ArgumentParser.add_subparsers(*[, title][, description][, prog][, parser_class][, action][, dest][, required][, help][, metavar])¶
許多程式將其功能分割為數個子命令,例如
svn程式可以呼叫svn checkout、svn update和svn commit等子命令。當程式執行多個需要不同種類命令列引數的不同功能時,以這種方式分割功能是特別好的做法。ArgumentParser透過add_subparsers()方法支援建立這類子命令。add_subparsers()方法通常不帶引數呼叫,並回傳一個特殊的 action 物件。此物件有一個方法add_parser(),它接受命令名稱和任何ArgumentParser建構函式引數,並回傳一個可以像往常一樣修改的ArgumentParser物件。參數的解釋:
title - 說明輸出中子剖析器群組的標題;預設情況下,若有提供 description 則為 "subcommands",否則使用位置引數的標題
description - 說明輸出中子剖析器群組的描述,預設為
Noneprog - 將與子命令說明一起顯示的用法資訊,預設為程式名稱和子剖析器引數之前的任何位置引數
parser_class - 將用來建立子剖析器實例的類別,預設為目前剖析器的類別(例如
ArgumentParser)action - 在命令列遇到此引數時要執行的基本 action 類型
dest - 用於儲存子命令名稱的屬性名稱;預設為
None且不儲存任何值required - 是否必須提供子命令,預設為
False(在 3.7 中新增)help - 說明輸出中子剖析器群組的說明,預設為
Nonemetavar - 在說明中呈現可用子命令的字串;預設為
None並以 {cmd1, cmd2, ..} 的形式呈現子命令
一些使用範例:
>>> # 建立頂層剖析器 >>> parser = argparse.ArgumentParser(prog='PROG') >>> parser.add_argument('--foo', action='store_true', help='foo help') >>> subparsers = parser.add_subparsers(help='subcommand help') >>> >>> # 建立 "a" 命令的剖析器 >>> parser_a = subparsers.add_parser('a', help='a help') >>> parser_a.add_argument('bar', type=int, help='bar help') >>> >>> # 建立 "b" 命令的剖析器 >>> parser_b = subparsers.add_parser('b', help='b help') >>> parser_b.add_argument('--baz', choices=('X', 'Y', 'Z'), help='baz help') >>> >>> # 剖析一些引數串列 >>> parser.parse_args(['a', '12']) Namespace(bar=12, foo=False) >>> parser.parse_args(['--foo', 'b', '--baz', 'Z']) Namespace(baz='Z', foo=True)
請注意
parse_args()回傳的物件只會包含主剖析器和命令列所選子剖析器的屬性(而非任何其他子剖析器)。因此在上面的範例中,當指定a命令時,只有foo和bar屬性存在;當指定b命令時,只有foo和baz屬性存在。同樣地,當從子剖析器請求說明訊息時,只會印出該特定剖析器的說明。說明訊息不會包含父剖析器或兄弟剖析器的訊息。(然而每個子剖析器命令的說明訊息可以透過如上所述向
add_parser()提供help=引數來給定。)>>> parser.parse_args(['--help']) usage: PROG [-h] [--foo] {a,b} ... positional arguments: {a,b} subcommand help a a help b b help options: -h, --help show this help message and exit --foo foo help >>> parser.parse_args(['a', '--help']) usage: PROG a [-h] bar positional arguments: bar bar help options: -h, --help show this help message and exit >>> parser.parse_args(['b', '--help']) usage: PROG b [-h] [--baz {X,Y,Z}] options: -h, --help show this help message and exit --baz {X,Y,Z} baz help
add_subparsers()方法也支援title和description關鍵字引數。當任一者存在時,子剖析器的命令會在說明輸出中以自己的群組出現。例如:>>> parser = argparse.ArgumentParser() >>> subparsers = parser.add_subparsers(title='subcommands', ... description='valid subcommands', ... help='additional help') >>> subparsers.add_parser('foo') >>> subparsers.add_parser('bar') >>> parser.parse_args(['-h']) usage: [-h] {foo,bar} ... options: -h, --help show this help message and exit subcommands: valid subcommands {foo,bar} additional help
此外,
add_parser()支援一個額外的 aliases 引數,它允許多個字串參照同一個子剖析器。這個範例像svn一樣,將co作為checkout的簡寫別名:>>> parser = argparse.ArgumentParser() >>> subparsers = parser.add_subparsers() >>> checkout = subparsers.add_parser('checkout', aliases=['co']) >>> checkout.add_argument('foo') >>> parser.parse_args(['co', 'bar']) Namespace(foo='bar')
add_parser()也支援一個額外的 deprecated 引數,它允許棄用子剖析器。>>> import argparse >>> parser = argparse.ArgumentParser(prog='chicken.py') >>> subparsers = parser.add_subparsers() >>> run = subparsers.add_parser('run') >>> fly = subparsers.add_parser('fly', deprecated=True) >>> parser.parse_args(['fly']) chicken.py: warning: command 'fly' is deprecated Namespace()
在 3.13 版被加入.
處理子命令的一個特別有效的方式是將
add_subparsers()方法的使用與set_defaults()的呼叫結合,使每個子剖析器知道它應該執行哪個 Python 函式。例如:>>> # 子命令函式 >>> def foo(args): ... print(args.x * args.y) ... >>> def bar(args): ... print('((%s))' % args.z) ... >>> # 建立頂層剖析器 >>> parser = argparse.ArgumentParser() >>> subparsers = parser.add_subparsers(required=True) >>> >>> # 建立 "foo" 命令的剖析器 >>> parser_foo = subparsers.add_parser('foo') >>> parser_foo.add_argument('-x', type=int, default=1) >>> parser_foo.add_argument('y', type=float) >>> parser_foo.set_defaults(func=foo) >>> >>> # 建立 "bar" 命令的剖析器 >>> parser_bar = subparsers.add_parser('bar') >>> parser_bar.add_argument('z') >>> parser_bar.set_defaults(func=bar) >>> >>> # 剖析引數並呼叫所選的函式 >>> args = parser.parse_args('foo 1 -x 2'.split()) >>> args.func(args) 2.0 >>> >>> # 剖析引數並呼叫所選的函式 >>> args = parser.parse_args('bar XYZYX'.split()) >>> args.func(args) ((XYZYX))
這樣你可以讓
parse_args()在引數剖析完成後負責呼叫適當的函式。像這樣將函式與 action 關聯通常是處理每個子剖析器不同動作的最簡單方式。然而如果有必要檢查被呼叫的子剖析器名稱,add_subparsers()呼叫的dest關鍵字引數可以達成此目的:>>> parser = argparse.ArgumentParser() >>> subparsers = parser.add_subparsers(dest='subparser_name') >>> subparser1 = subparsers.add_parser('1') >>> subparser1.add_argument('-x') >>> subparser2 = subparsers.add_parser('2') >>> subparser2.add_argument('y') >>> parser.parse_args(['2', 'frobble']) Namespace(subparser_name='2', y='frobble')
在 3.7 版的變更: 新增 required 僅限關鍵字參數。
在 3.14 版的變更: 子剖析器的 prog 不再受主剖析器中自訂用法訊息的影響。
FileType 物件¶
- class argparse.FileType(mode='r', bufsize=-1, encoding=None, errors=None)¶
FileType工廠建立可以傳給ArgumentParser.add_argument()的 type 引數的物件。以FileType物件作為其型別的引數會以請求的模式、緩衝區大小、編碼和錯誤處理開啟命令列引數作為檔案(更多詳情請參閱open()函式):>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--raw', type=argparse.FileType('wb', 0)) >>> parser.add_argument('out', type=argparse.FileType('w', encoding='UTF-8')) >>> parser.parse_args(['--raw', 'raw.dat', 'file.txt']) Namespace(out=<_io.TextIOWrapper name='file.txt' mode='w' encoding='UTF-8'>, raw=<_io.FileIO name='raw.dat' mode='wb'>)
FileType 物件能理解偽引數
'-',並自動將其轉換為可讀FileType物件的sys.stdin和可寫FileType物件的sys.stdout:>>> parser = argparse.ArgumentParser() >>> parser.add_argument('infile', type=argparse.FileType('r')) >>> parser.parse_args(['-']) Namespace(infile=<_io.TextIOWrapper name='<stdin>' encoding='UTF-8'>)
備註
如果一個引數使用了 FileType 然後後續的引數失敗了,雖然會報告錯誤但檔案不會自動關閉。這也可能覆蓋輸出檔案。在這種情況下,最好等到剖析器執行完畢後,再使用
with陳述式來管理檔案。在 3.4 版的變更: 新增了 encodings 和 errors 參數。
在 3.14 版之後被棄用.
引數群組¶
- ArgumentParser.add_argument_group(title=None, description=None, *[, argument_default][, conflict_handler])¶
預設情況下,
ArgumentParser在顯示說明訊息時會將命令列引數分成「位置引數」和「選項」兩組。當引數有比此預設分組更好的概念性分組時,可以使用add_argument_group()方法建立適當的群組:>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False) >>> group = parser.add_argument_group('group') >>> group.add_argument('--foo', help='foo help') >>> group.add_argument('bar', help='bar help') >>> parser.print_help() usage: PROG [--foo FOO] bar group: bar bar help --foo FOO foo help
add_argument_group()方法回傳一個引數群組物件,它具有與一般ArgumentParser相同的add_argument()方法。當引數被加入群組時,剖析器會像處理正常引數一樣處理它,但在說明訊息中以獨立的群組顯示該引數。add_argument_group()方法接受 title 和 description 引數,可以用來自訂此顯示:>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False) >>> group1 = parser.add_argument_group('group1', 'group1 description') >>> group1.add_argument('foo', help='foo help') >>> group2 = parser.add_argument_group('group2', 'group2 description') >>> group2.add_argument('--bar', help='bar help') >>> parser.print_help() usage: PROG [--bar BAR] foo group1: group1 description foo foo help group2: group2 description --bar BAR bar help
選擇性的僅限關鍵字參數 argument_default 和 conflict_handler 允許對引數群組的行為進行更精細的控制。這些參數的意義與
ArgumentParser建構函式中的相同,但專門適用於引數群組而非整個剖析器。請注意,任何不在使用者定義群組中的引數會歸入一般的「位置引數」和「可選引數」區段。
自從版本 3.11 後不推薦使用,已從版本 3.14 中移除。: 在引數群組上呼叫
add_argument_group()現在會引發例外。這種巢狀用法從未被支援,通常無法正確運作,是因為繼承而無意間被公開出來的。在 3.14 版之後被棄用: 將 prefix_chars 傳給
add_argument_group()的用法現在已棄用。
互斥¶
- ArgumentParser.add_mutually_exclusive_group(required=False)¶
建立一個互斥群組。
argparse會確保互斥群組中只有一個引數出現在命令列上:>>> parser = argparse.ArgumentParser(prog='PROG') >>> group = parser.add_mutually_exclusive_group() >>> group.add_argument('--foo', action='store_true') >>> group.add_argument('--bar', action='store_false') >>> parser.parse_args(['--foo']) Namespace(bar=True, foo=True) >>> parser.parse_args(['--bar']) Namespace(bar=False, foo=False) >>> parser.parse_args(['--foo', '--bar']) usage: PROG [-h] [--foo | --bar] PROG: error: argument --bar: not allowed with argument --foo
add_mutually_exclusive_group()方法也接受一個 required 引數,用來指示至少需要一個互斥引數:>>> parser = argparse.ArgumentParser(prog='PROG') >>> group = parser.add_mutually_exclusive_group(required=True) >>> group.add_argument('--foo', action='store_true') >>> group.add_argument('--bar', action='store_false') >>> parser.parse_args([]) usage: PROG [-h] (--foo | --bar) PROG: error: one of the arguments --foo --bar is required
請注意,目前互斥引數群組不支援
add_argument_group()的 title 和 description 引數。然而互斥群組可以加入到具有標題和描述的引數群組中。例如:>>> parser = argparse.ArgumentParser(prog='PROG') >>> group = parser.add_argument_group('Group title', 'Group description') >>> exclusive_group = group.add_mutually_exclusive_group(required=True) >>> exclusive_group.add_argument('--foo', help='foo help') >>> exclusive_group.add_argument('--bar', help='bar help') >>> parser.print_help() usage: PROG [-h] (--foo FOO | --bar BAR) options: -h, --help show this help message and exit Group title: Group description --foo FOO foo help --bar BAR bar help
自從版本 3.11 後不推薦使用,已從版本 3.14 中移除。: 在互斥群組上呼叫
add_argument_group()或add_mutually_exclusive_group()現在會引發例外。這種巢狀用法從未支援,通常無法正確運作,且是因為繼承而無意間被公開出來的。
剖析器預設值¶
- ArgumentParser.set_defaults(**kwargs)¶
在大多數情況下,
parse_args()回傳物件的屬性會完全由檢查命令列引數和引數 action 來決定。set_defaults()允許加入一些無需檢查命令列即可決定的額外屬性:>>> parser = argparse.ArgumentParser() >>> parser.add_argument('foo', type=int) >>> parser.set_defaults(bar=42, baz='badger') >>> parser.parse_args(['736']) Namespace(bar=42, baz='badger', foo=736)
請注意,預設值可以在剖析器層級使用
set_defaults()設定,也可以在引數層級使用add_argument()設定。如果兩者都為同一個引數呼叫,會使用最後設定的預設值:>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', default='bar') >>> parser.set_defaults(foo='spam') >>> parser.parse_args([]) Namespace(foo='spam')
在使用多個剖析器時,剖析器層級的預設值可能特別有用。請參閱
add_subparsers()方法以了解這類範例。
- ArgumentParser.get_default(dest)¶
取得命名空間屬性的預設值,由
add_argument()或set_defaults()設定:>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', default='badger') >>> parser.get_default('foo') 'badger'
印出幫助訊息¶
在大多數典型的應用程式中,parse_args() 會處理格式化和印出任何用法或錯誤訊息。然而,有幾個格式化方法可以使用:
- ArgumentParser.print_usage(file=None)¶
印出
ArgumentParser在命令列上呼叫方式的簡短描述。如果 file 為None,則假設為sys.stdout。
- ArgumentParser.print_help(file=None)¶
印出說明訊息,包括程式用法和在
ArgumentParser中註冊的引數相關資訊。如果 file 為None,假設為sys.stdout。
這些方法也有變體,它們只回傳字串而非印出它:
- ArgumentParser.format_usage()¶
回傳一個字串,包含
ArgumentParser在命令列上的呼叫方式的簡短描述。
- ArgumentParser.format_help()¶
回傳一個字串,包含說明訊息,包括程式用法和在
ArgumentParser中註冊的引數相關資訊。
部分剖析¶
- ArgumentParser.parse_known_args(args=None, namespace=None)¶
有時候一個腳本只需要處理特定的一組命令列引數,將任何未辨識的引數留給另一個腳本或程式。在這些情況下,
parse_known_args()方法可能很有用。此方法的運作方式類似
parse_args(),但它不會對額外的、未辨識的引數引發錯誤,而是會只剖析已知的引數並回傳一個包含填充後的命名空間和任何未辨識引數串列的二元素元組。>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action='store_true') >>> parser.add_argument('bar') >>> parser.parse_known_args(['--foo', '--badger', 'BAR', 'spam']) (Namespace(bar='BAR', foo=True), ['--badger', 'spam'])
警告
前綴匹配規則適用於 parse_known_args()。即使選項只是其已知選項之一的前綴,剖析器也可能消耗它,而非將其留在剩餘引數串列中。
自訂檔案剖析¶
- ArgumentParser.convert_arg_line_to_args(arg_line)¶
從檔案讀取的引數(請參閱
ArgumentParser建構函式的 fromfile_prefix_chars 關鍵字引數)每行讀取一個引數。可以覆寫convert_arg_line_to_args()以進行更精細的讀取。此方法接受單個引數 arg_line,它是從引數檔案讀取的字串。它回傳從此字串剖析出的引數串列。此方法對從引數檔案讀取的每一行依序呼叫一次。
此方法的一個有用覆寫是將每個以空格分隔的詞作為引數。以下範例示範了如何做到這一點:
class MyArgumentParser(argparse.ArgumentParser): def convert_arg_line_to_args(self, arg_line): return arg_line.split()
退出方法¶
- ArgumentParser.exit(status=0, message=None)¶
此方法終止程式,以指定的 status 退出,並在退出前(如果有提供的話)向
sys.stderr印出一個 message。使用者可以覆寫此方法來以不同方式處理這些步驟:class ErrorCatchingArgumentParser(argparse.ArgumentParser): def exit(self, status=0, message=None): if status: raise Exception(f'Exiting because of an error: {message}') exit(status)
- ArgumentParser.error(message)¶
此方法將用法訊息(包含 message)印出到
sys.stderr,並以狀態碼 2 終止程式。
交錯剖析¶
- ArgumentParser.parse_intermixed_args(args=None, namespace=None)¶
- ArgumentParser.parse_known_intermixed_args(args=None, namespace=None)¶
許多 Unix 命令允許使用者將可選引數與位置引數交錯使用。
parse_intermixed_args()和parse_known_intermixed_args()方法支援此剖析風格。這些剖析器不支援所有
argparse功能,如果使用了不支援的功能會引發例外。特別是不支援子剖析器,以及同時包含可選引數和位置引數的互斥群組。以下範例展示了
parse_known_args()和parse_intermixed_args()之間的差異:前者回傳['2', '3']作為未剖析的引數,而後者將所有位置引數收集到rest中。>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo') >>> parser.add_argument('cmd') >>> parser.add_argument('rest', nargs='*', type=int) >>> parser.parse_known_args('doit 1 --foo bar 2 3'.split()) (Namespace(cmd='doit', foo='bar', rest=[1]), ['2', '3']) >>> parser.parse_intermixed_args('doit 1 --foo bar 2 3'.split()) Namespace(cmd='doit', foo='bar', rest=[1, 2, 3])
parse_known_intermixed_args()回傳一個二元素元組,包含填充後的命名空間和剩餘引數字串的串列。parse_intermixed_args()在有任何剩餘未剖析的引數字串時會引發錯誤。在 3.7 版被加入.
註冊自訂型別或 action¶
- ArgumentParser.register(registry_name, value, object)¶
有時候想要在錯誤訊息中使用自訂字串以提供更友善的輸出。在這些情況下,可以使用
register()向剖析器註冊自訂 action 或型別,讓你可以透過註冊名稱而非可呼叫物件名稱來參照型別。register()方法接受三個引數——registry_name,指定用於儲存物件的內部登錄檔(例如action、type);value,用於註冊物件的鍵值;以及 object,要註冊的可呼叫物件。以下範例展示如何向剖析器註冊自訂型別:
>>> import argparse >>> parser = argparse.ArgumentParser() >>> parser.register('type', 'hexadecimal integer', lambda s: int(s, 16)) >>> parser.add_argument('--foo', type='hexadecimal integer') _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type='hexadecimal integer', choices=None, required=False, help=None, metavar=None, deprecated=False) >>> parser.parse_args(['--foo', '0xFA']) Namespace(foo=250) >>> parser.parse_args(['--foo', '1.2']) usage: PROG [-h] [--foo FOO] PROG: error: argument --foo: invalid 'hexadecimal integer' value: '1.2'
例外¶
- exception argparse.ArgumentError¶
建立或使用引數(可選或位置引數)時的錯誤。
此例外的字串值是訊息,附帶了導致錯誤的引數的相關資訊。
- exception argparse.ArgumentTypeError¶
當將命令列字串轉換為型別時出錯時引發。
指南與教學