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(suggest_on_error=True)
>>> parser.add_argument('--action', choices=['debug', 'dryrun'])
>>> parser.parse_args(['--action', 'debugg'])
usage: tester.py [-h] [--action {debug,dryrun}]
tester.py: error: argument --action: invalid choice: 'debugg', maybe you meant 'debug'? (choose from debug, dryrun)
如果你正在撰寫需要與舊版 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 - 引數的使用是否已被棄用。
The method returns an
Actionobject representing the argument.
以下各節描述了這些參數的使用方式。
name or flags¶
add_argument() 方法必須知道預期的是可選引數(如 -f 或 --foo)還是位置引數(如檔案名稱的串列)。因此,傳給 add_argument() 的第一個引數必須是一系列旗標或一個簡單的引數名稱。
例如,可選引數可以像這樣建立:
>>> parser.add_argument('-f', '--foo')
而位置引數可以像這樣建立:
>>> parser.add_argument('bar')
當呼叫 parse_args() 時,可選引數會透過 - 前綴來辨識,其餘的引數則假設為位置引數:
>>> parser = argparse.ArgumentParser(