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')           # positional argument
parser.add_argument('-c', '--count')      # option that takes a value
parser.add_argument('-v', '--verbose',
                    action='store_true')  # on/off flag

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,再後跟模組或包的名稱。

這個預設值幾乎總是理想的,因為它會使幫助訊息與在命令列上呼叫程式時使用的字串相匹配。然而,要更改此預設行為,可以使用 prog= 引數向 ArgumentParser 提供另一個值。

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

一些程式喜歡在引數描述之後顯示對程式的額外描述。可以使用 epilog= 引數向 ArgumentParser 指定此類文字。

>>> 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= 文字預設是自動換行的,但可以使用 formatter_class 引數調整此行為。

parents

有時,幾個解析器會共享一組共同的引數。與其重複定義這些引數,不如使用一個包含所有共享引數的解析器,並將其傳遞給 ArgumentParserparents= 引數。 parents= 引數接受一個 ArgumentParser 物件列表,從中收集所有的位置和可選操作,並將這些操作新增到正在構造的 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

有時,在處理一個特別長的引數列表時,將引數列表儲存在一個檔案中而不是在命令列上輸入可能會更有意義。如果向 ArgumentParser 建構函式提供了 fromfile_prefix_chars= 引數,那麼以任何指定字元開頭的引數都將被視為檔案,並被其包含的引數所替換。例如:

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

備註

空行被視為空字串 (''),它允許作為值,但不允許作為引數。被讀取為空引數的空行將導致“無法識別的引數”錯誤。

ArgumentParser 使用檔案系統編碼和錯誤處理程式來讀取包含引數的檔案。

fromfile_prefix_chars= 引數預設為 None,這意味著引數永遠不會被視為檔案引用。

在 3.12 版更改: ArgumentParser 更改了讀取引數檔案的編碼和錯誤處理方式,從預設(例如 locale.getpreferredencoding(False)"strict")改為使用檔案系統編碼和錯誤處理程式。在 Windows 上,引數檔案應以 UTF-8 編碼而不是 ANSI 內碼表編碼。

argument_default

通常,引數的預設值是透過向 add_argument() 傳遞一個 `default` 值,或者透過呼叫帶有特定名稱-值對集合的 set_defaults() 方法來指定的。然而,有時為引數指定一個單一的解析器範圍的預設值可能很有用。這可以透過向 ArgumentParser 傳遞 argument_default= 關鍵字引數來實現。例如,要在 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 物件不允許兩個具有相同選項字串的動作。預設情況下,如果嘗試建立一個與已使用選項字串衝突的引數,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

請注意,ArgumentParser 物件僅在其所有選項字串都被覆蓋時才會移除一個動作。因此,在上面的示例中,舊的 -f/--foo 動作被保留為 -f 動作,因為只有 --foo 選項字串被覆蓋了。

add_help

預設情況下,ArgumentParser 物件會新增一個選項,該選項僅顯示解析器的幫助資訊。如果在命令列中提供了 -h--help,則會列印 ArgumentParser 的幫助資訊。

偶爾,停用此幫助選項的新增可能很有用。這可以透過將 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 來啟用該功能。請注意,這僅適用於指定的 `choices` 是字串的引數。

>>> 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'])

在 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 - 在命令列中遇到此引數時要採取的基本操作型別。

  • nargs - 應該消耗的命令列引數的數量。

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

  • 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 會自動處理引數的內部命名和顯示名稱,無需額外配置即可簡化流程。因此,你不需要指定 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 物件將命令列引數與動作關聯起來。這些動作可以對與其關聯的命令列引數執行幾乎任何操作,儘管大多數動作只是向 parse_args() 返回的物件新增一個屬性。action 關鍵字引數指定了應如何處理命令列引數。提供的動作為:

  • 'store' - 這只是儲存引數的值。這是預設的動作。

  • 'store_const' - 這會儲存由 const 關鍵字引數指定的值;請注意,const 關鍵字引數預設為 None'store_const' 動作最常用於指定某種標誌的可選引數。例如:

    >>> 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' 動作通常很有用。例如:

    >>> 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' 動作通常與 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)
    

    請注意,*default* 將為 None,除非顯式設定為 *0*。

  • 'help' - 這會列印當前解析器中所有選項的完整幫助資訊,然後退出。預設情況下,會自動向解析器新增一個幫助動作。有關如何建立輸出的詳細資訊,請參見 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)或其他實現相同介面的物件來指定任意動作。只有消耗命令列引數的動作(例如 'store''append''extend',或非零 nargs 的自定義動作)可以與位置引數一起使用。

建立自定義動作的推薦方法是擴充套件 Action,重寫 __call__() 方法,並可選擇地重寫 __init__()format_usage() 方法。你也可以使用 register() 方法註冊自定義動作,並透過其註冊名稱引用它們。

一個自定義動作的示例:

>>> 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 物件通常將一個命令列引數與一個要執行的動作關聯起來。nargs 關鍵字引數將不同數量的命令列引數與一個單一的動作關聯起來。另請參見 指定歧義引數。支援的值有:

  • 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 決定。通常這意味著將消耗一個命令列引數並生成一個單個專案(而不是一個列表)。不消耗命令列引數的動作(例如 'store_const')設定 nargs=0

const

add_argument()const 引數用於儲存不從命令列讀取但對於各種 ArgumentParser 動作是必需的常量值。它最常見的兩個用途是:

  • add_argument() 被呼叫時帶有 action='store_const'action='append_const'。這些動作將 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)

如果目標名稱空間已經設定了一個屬性,動作的 *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)

對於必需的引數,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。這通常不是所期望的。

總的來說,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 並在你的應用程式程式碼中處理轉換。

格式化的選項會覆蓋預設的 *metavar*,後者通常派生自 *dest*。這通常是你想要的,因為使用者永遠看不到 *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)sadd_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

由於幫助字串支援 %-格式化,如果你想在幫助字串中出現一個字面的 %,你必須將其轉義為 %%

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 動作會新增某個值作為 parse_args() 返回物件的一個屬性。該屬性的名稱由 add_argument()dest 關鍵字引數決定。對於位置引數動作,dest 通常作為第一個引數提供給 add_argument()

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('bar')
>>> parser.parse_args(['XXX'])
Namespace(bar='XXX')

對於可選引數的動作,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 本身,Action 類必須接受兩個位置引數以及傳遞給 ArgumentParser.add_argument() 的任何關鍵字引數。

Action 的例項(或傳遞給 action 引數的任何可呼叫物件的返回值)應定義 dest, option_strings, default, type, required, help 等屬性。確保這些屬性被定義的最簡單方法是呼叫 Action.__init__()

__call__(parser, namespace, values, option_string=None)

Action 例項應該是可呼叫的,因此子類必須重寫 __call__() 方法,該方法應接受四個引數

  • parser - 包含此動作的 ArgumentParser 物件。

  • namespace - 將由 parse_args() 返回的 Namespace 物件。大多數動作使用 setattr() 向該物件新增屬性。

  • values - 關聯的命令列引數,並已應用任何型別轉換。型別轉換透過 add_argument()type 關鍵字引數指定。

  • option_string - 用於呼叫此動作的選項字串。如果動作與位置引數關聯,option_string 引數是可選的,並且將不存在。

__call__() 方法可以執行任意操作,但通常會根據 destvaluesnamespace 上設定屬性。

format_usage()

Action 子類可以定義一個不帶引數的 format_usage() 方法,它返回一個字串,該字串將在列印程式用法時使用。如果未提供此方法,將使用合理的預設值。

class argparse.BooleanOptionalAction

Action 的一個子類,用於處理帶有肯定和否定選項的布林標誌。新增一個如 --foo 這樣的引數會自動建立 --foo--no-foo 兩個選項,分別儲存 TrueFalse

>>> 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() 的文件。

  • args - 要解析的字串列表。預設值取自 sys.argv

  • namespace - 用於接收屬性的物件。預設是一個新的空 Namespace 物件。

選項值語法

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='?')

>>> # invalid type
>>> parser.parse_args(['--foo', 'spam'])
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: argument --foo: invalid int value: 'spam'

>>> # invalid option
>>> parser.parse_args(['--bar'])
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: no such option: --bar

>>> # wrong number of arguments
>>> 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='?')

>>> # no negative number options, so -1 is a positional argument
>>> parser.parse_args(['-x', '-1'])
Namespace(foo=None, x='-1')

>>> # no negative number options, so -1 and -5 are positional arguments
>>> 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='?')

>>> # negative number options present, so -1 is an option
>>> parser.parse_args(['-1', 'X'])
Namespace(foo=None, one='X')

>>> # negative number options present, so -2 is an option
>>> parser.parse_args(['-2'])
usage: PROG [-h] [-1 ONE] [foo]
PROG: error: no such option: -2

>>> # negative number options present, so both -1s are options
>>> 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 指南中關於歧義引數 的部分以獲取更多細節。

引數縮寫(字首匹配)

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

Namespace 物件

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 checkoutsvn updatesvn commit 等子命令。當一個程式執行多個需要不同型別命令列引數的不同功能時,以這種方式劃分功能可能是一個特別好的主意。ArgumentParser 支援透過 add_subparsers() 方法建立此類子命令。 add_subparsers() 方法通常不帶引數呼叫,並返回一個特殊的動作物件。該物件只有一個方法,add_parser(),它接受一個命令名和任何 ArgumentParser 建構函式引數,並返回一個可以像往常一樣修改的 ArgumentParser 物件。

引數說明

  • title - 幫助輸出中子解析器組的標題;如果提供了 description,則預設為 “subcommands”,否則使用位置引數的標題

  • description - 幫助輸出中子解析器組的描述,預設為 None

  • prog - 將與子命令幫助一起顯示的用法資訊,預設為程式名稱和子解析器引數之前的任何位置引數

  • parser_class - 將用於建立子解析器例項的類,預設為當前解析器的類(例如 ArgumentParser

  • action - 在命令列中遇到此引數時要採取的基本動作型別

  • dest - 子命令名稱將儲存在其下的屬性名稱;預設為 None,不儲存任何值

  • required - 是否必須提供子命令,預設為 False (在 3.7 版本中新增)

  • help - 幫助輸出中子解析器組的幫助資訊,預設為 None

  • metavar - 在幫助資訊中表示可用子命令的字串;預設為 None,並以 {cmd1, cmd2, ..} 的形式呈現子命令

一些用法示例

>>> # create the top-level parser
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', action='store_true', help='foo help')
>>> subparsers = parser.add_subparsers(help='subcommand help')
>>>
>>> # create the parser for the "a" command
>>> parser_a = subparsers.add_parser('a', help='a help')
>>> parser_a.add_argument('bar', type=int, help='bar help')
>>>
>>> # create the parser for the "b" command
>>> parser_b = subparsers.add_parser('b', help='b help')
>>> parser_b.add_argument('--baz', choices=('X', 'Y', 'Z'), help='baz help')
>>>
>>> # parse some argument lists
>>> 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 命令時,只有 foobar 屬性存在,而當指定 b 命令時,只有 foobaz 屬性存在。

同樣,當從子解析器請求幫助訊息時,將只打印該特定解析器的幫助資訊。幫助訊息不會包括父解析器或同級解析器的訊息。(然而,可以透過向 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() 方法還支援 titledescription 關鍵字引數。當其中任何一個存在時,子解析器的命令將出現在幫助輸出中它們自己的組中。例如

>>> 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 函式。例如

>>> # subcommand functions
>>> def foo(args):
...     print(args.x * args.y)
...
>>> def bar(args):
...     print('((%s))' % args.z)
...
>>> # create the top-level parser
>>> parser = argparse.ArgumentParser()
>>> subparsers = parser.add_subparsers(required=True)
>>>
>>> # create the parser for the "foo" command
>>> 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)
>>>
>>> # create the parser for the "bar" command
>>> parser_bar = subparsers.add_parser('bar')
>>> parser_bar.add_argument('z')
>>> parser_bar.set_defaults(func=bar)
>>>
>>> # parse the args and call whatever function was selected
>>> args = parser.parse_args('foo 1 -x 2'.split())
>>> args.func(args)
2.0
>>>
>>> # parse the args and call whatever function was selected
>>> args = parser.parse_args('bar XYZYX'.split())
>>> args.func(args)
((XYZYX))

透過這種方式,您可以讓 parse_args() 在引數解析完成後呼叫適當的函式。像這樣將函式與動作關聯通常是處理每個子解析器不同動作的最簡單方法。但是,如果需要檢查被呼叫的子解析器的名稱,可以使用 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 版更改: 添加了 encodingserrors 引數。

自 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() 方法返回一個引數組物件,該物件具有一個 add_argument() 方法,就像常規的 ArgumentParser 一樣。當引數新增到組中時,解析器會像處理普通引數一樣處理它,但在幫助訊息中將該引數顯示在單獨的組中。 add_argument_group() 方法接受 titledescription 引數,可用於自定義此顯示

>>> 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_defaultconflict_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()titledescription 引數。但是,可以將互斥組新增到具有標題和描述的引數組中。例如

>>> 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() 返回的物件的屬性將完全由檢查命令列引數和引數動作來確定。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)

請注意,解析器級別的預設值總是會覆蓋引數級別的預設值

>>> 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 的簡要說明。如果 fileNone,則假定為 sys.stdout

ArgumentParser.print_help(file=None)

列印幫助訊息,包括程式用法和有關向 ArgumentParser 註冊的引數的資訊。如果 fileNone,則假定為 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)

此方法向 sys.stderr 列印一條用法訊息,包括 message,並以狀態碼 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 版本加入。

註冊自定義型別或動作

ArgumentParser.register(registry_name, value, object)

有時,為了提供更友好的使用者輸出,希望在錯誤訊息中使用自定義字串。在這些情況下,可以使用 register() 向解析器註冊自定義動作或型別,並允許您透過其註冊名稱而不是其可呼叫名稱來引用型別。

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

在將命令列字串轉換為型別時出現問題時引發。

指南和教程