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(