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