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_errorcolor 參數。

以下各節描述了這些參數的使用方式。

prog

預設情況下,ArgumentParser 會根據 Python 直譯器的執行方式計算要在說明訊息中顯示的程式名稱:

  • 如果傳入的引數是一個檔案,則使用 sys.argv[0]基底名稱

  • 如果傳入的引數是一個目錄或 zip 檔案,則使用 Python 直譯器名稱加上 sys.argv[0]

  • 如果使用了 -m 選項,則使用 Python 直譯器名稱加上 -m 再加上模組或套件名稱。

這個預設值幾乎都不會錯,因為它會使說明訊息與命令列上呼叫程式時所用的字串一致。然而,若要更改此預設行為,可以使用 ArgumentParserprog= 引數提供另一個值:

>>> 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(),或是將 progusage 引數傳給 add_parser() 以確保子剖析器之間的命令前綴和用法資訊一致。

description

大多數對 ArgumentParser 建構函式的呼叫會使用 description= 關鍵字引數。此引數提供程式功能和運作方式的簡短描述。在說明訊息中,這個描述會顯示在命令列用法字串和各引數的說明訊息之間。

預設情況下,該描述會被自動斷行來配合給定的空間。若要更改此行為,請參閱 formatter_class 引數。

epilog

有些程式喜歡在引數描述之後顯示程式的額外說明。可以使用 ArgumentParserepilog= 引數來指定這類文字:

>>> 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= 文字預設會被自動斷行,但可以透過 ArgumentParserformatter_class 引數調整此行為。

parents

有時候多個剖析器會共用一組共同的引數。與其重複定義這些引數,不如使用一個包含所有共用引數的剖析器,並將其傳給 ArgumentParserparents= 引數。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

RawDescriptionHelpFormatterRawTextHelpFormatter 提供了對文字描述顯示方式的更多控制。預設情況下,ArgumentParser 物件會在命令列說明訊息中為 descriptionepilog 文字自動斷行:

>>> 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= 傳入,表示 descriptionepilog 已經正確格式化,不應自動斷行:

>>> 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

當你將引數串列傳給 ArgumentParserparse_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' 提供給 ArgumentParserconflict_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

當你將無效的引數串列傳給 ArgumentParserparse_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_COLORPYTHON_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 - 應消耗的命令列引數數量。

  • const - 某些 actionnargs 選擇所需的常數值。

  • default - 如果引數不在命令列中且不在命名空間物件中時所產生的值。

  • type - 命令列引數應轉換成的型別。

  • choices - 引數允許值的序列。

  • required - 命令列選項是否可省略(僅限可選引數)。

  • help - 引數功能的簡短描述。

  • metavar - 引數在用法訊息中的名稱。

  • dest - 要加入到 parse_args() 回傳物件中的屬性名稱。

  • deprecated - 引數的使用是否已被棄用。

The method returns an Action object 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(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 會自動處理引數的內部命名和顯示名稱,簡化流程而不需要額外設定。因此,你不需要指定 destmetavar 參數。對於可選的引數,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' 的特殊情況,分別儲存值 TrueFalse,預設值為 FalseTrue

    >>> 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 關鍵字引數值 '+''*' 一起使用。請注意,當 nargsNone(預設值)或 '?' 時,引數字串的每個字元都會被附加到串列中。使用範例:

    >>> 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

預設情況下,剖析器將命令列引數作為簡單字串讀取。然而命令列字串往往應直譯為另一種型別,例如 floatintadd_argument()type 關鍵字允許執行任何必要的型別檢查和型別轉換。

如果 type 關鍵字與 default 關鍵字一起使用,型別轉換器只會在預設值為字串時套用。

type 的引數可以是一個接受單個字串的可呼叫物件,或是已註冊型別的名稱(請參閱 register())。如果函式引發 ArgumentTypeErrorTypeErrorValueError,剖析器會捕捉例外並顯示格式良好的錯誤訊息。其他例外型別則不處理。

常見的內建型別和函式可以作為型別轉換器使用:

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。這通常不是期望的行為::

>>> parser = argparse.ArgumentParser()
>>> _ = parser.add_argument('--verbose', type=bool)
>>> parser.parse_args(['--verbose', 'False'])
Namespace(verbose=True)

See BooleanOptionalAction or action='store_true' for common alternatives.

一般而言,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

如範例所示,如果一個選項被標記為 requiredparse_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)指定引數是否已棄用並將在未來移除。對於引數,如果 deprecatedTrue,那麼使用該引數時會向 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 參數的可呼叫物件的回傳值)應定義 destoption_stringsdefaulttyperequiredhelp 等屬性。確保這些屬性被定義的最簡單方式是呼叫 Action.__init__()

__call__(