天天看點

淺入淺出python中的argparse子產品

argparse是python的一個improving子產品,借助此子產品我們可以輕松編寫使用者友好的指令行接口。以下是python官方的一個示例,我們從這個示例開始對argparse進行深入:

import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                    help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=max,
                    help='sum the integers (default: find the max)')

args = parser.parse_args()
print(args.accumulate(args.integers))
           

假設上面的 Python 代碼儲存在名為 prog.py 的檔案中,它可以在指令行運作并提供有用的幫助資訊(ps:也必須在指令行運作,否則則報錯[An exception has occurred, use %tb to see the full traceback.]):

$ **python prog.py -h**
usage: prog.py [-h] [--sum] N [N ...]

Process some integers.

positional arguments:
 N           an integer for the accumulator

optional arguments:
 -h, --help  show this help message and exit
 --sum       sum the integers (default: find the max)

           

當我們帶入參數進行運算時,會輸出我們所定義的結果:

$ python prog.py 1 2 3 4
4

$ python prog.py 1 2 3 4 --sum
10
           

接下來我們就為何輸出,以及程式中的各參數進行解讀,弄個來龍去脈。

使用argparse的第一步是建立一個 ArgumentParser 對象,ArgumentParser 對象包含将指令行解析成 Python 資料類型所需的全部資訊

parser = argparse.ArgumentParser(description='Process some integers.')
#這是建立的最簡單的一個對象,一般我們要合理使用argparse還必須添加合适的參數
           

為ArgumentParser 添加參數我們是通過add_argument()方法實作的,下面我将對要添加的參數進行進一步的解析:

ArgumentParser 通過 parse_args() 方法解析參數。它将檢查指令行,把每個參數轉換為适當的類型然後調用相應的操作。在大多數情況下,這意味着一個簡單的 Namespace 對象将從指令行解析出的屬性建構(這是官網原話翻譯而來):

>>> parser.parse_args(['--sum', '7', '-1', '42'])
Namespace(accumulate=<built-in function sum>, integers=[7, -1, 42]),
           

ArgumentParse的對象參數表示為:

建立一個新的 ArgumentParser 對象。所有的參數都應當作為關鍵字參數傳入。每個參數在下面都有它更詳細的描述,但簡而言之,它們是:

  • prog - 程式的名稱(預設值: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)

1、prog

預設情況下,ArgumentParser 對象使用 sys.argv[0] 來确定如何在幫助消息中顯示程式名稱,比如有如下代碼myprog.py:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', help='foo help')
args = parser.parse_args()
           

當我們需要檢視幫助資訊時,會有如下顯示:

$ python myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]
           

如果我們覺得系統預設的提示資訊還不夠想自己自定義添加一些–help資訊,我們則可以使用prog參數來為ArgumentParser指定另外一個值:

>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser.print_help()
usage: myprogram [-h]

optional arguments:
 -h, --help  show this help message and exit
           

2、useage

預設情況下,ArgumentParser 根據它包含的參數來建構用法消息:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', nargs='?', help='foo help')
>>> parser.add_argument('bar', nargs='+', help='bar help')
>>> parser.print_help()
usage: PROG [-h] [--foo [FOO]] bar [bar ...]

positional arguments:
 bar          bar help

optional arguments:
 -h, --help   show this help message and exit
 --foo [FOO]  foo help
           

可以通過 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

optional arguments:
 -h, --help   show this help message and exit
 --foo [FOO]  foo help
           

3、description

大多數對 ArgumentParser 構造方法的調用都會使用 description= 關鍵字參數。這個參數簡要描述這個程度做什麼以及怎麼做。在幫助消息中,這個描述會顯示在指令行用法字元串和各種參數的幫助消息之間:

>>> parser = argparse.ArgumentParser(description='A foo that bars')
>>> parser.print_help()
usage: argparse.py [-h]

A foo that bars

optional arguments:
 -h, --help  show this help message and exit
           

4、epilog

一些程式喜歡在 description 參數後顯示額外的對程式的描述。這種文字能夠通過給 ArgumentParser:: 提供 epilog= 參數而被指定

>>> parser = argparse.ArgumentParser(
...     description='A foo that bars',
...     epilog="And that's how you'd foo a bar")
>>> parser.print_help()
usage: argparse.py [-h]

A foo that bars

optional arguments:
 -h, --help  show this help message and exit

And that's how you'd foo a bar
           

5、parents

有些時候,少數解析器會使用同一系列參數。 單個解析器能夠通過提供 parents= 參數給 ArgumentParser 而使用相同的參數而不是重複這些參數的定義。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)
           

6、formatter_class

ArgumentParser 對象允許通過指定備用格式化類來自定義幫助格式。目前,有四種這樣的類。

  1. class argparse.RawDescriptionHelpFormatter
  2. class argparse.RawTextHelpFormatter
  3. class argparse.ArgumentDefaultsHelpFormatter
  4. class argparse.MetavarTypeHelpFormatter

RawDescriptionHelpFormatter 和 RawTextHelpFormatter 在正文的描述和展示上給與了更多的控制。ArgumentParser 對象會将 description 和 epilog 的文字在指令行中自動換行。

>>> parser = argparse.ArgumentParser(
...     prog='PROG',
...     description='''this description
...         was indented weird
...             but that is okay''',
...     epilog='''
...             likewise for this epilog whose whitespace will
...         be cleaned up and whose words will be wrapped
...         across a couple lines''')
>>> parser.print_help()
usage: PROG [-h]

this description was indented weird but that is okay

optional arguments:
 -h, --help  show this help message and exit

likewise for this epilog whose whitespace will be cleaned up and whose words
will be wrapped across a couple lines
           

傳 RawDescriptionHelpFormatter 給 formatter_class= 表示 description 和 epilog 已經被正确的格式化了,不能在指令行中被自動換行:

>>> parser = argparse.ArgumentParser(
...     prog='PROG',
...     formatter_class=argparse.RawDescriptionHelpFormatter,
...     description=textwrap.dedent('''\
...         Please do not mess up this text!
...         --------------------------------
...             I have indented it
...             exactly the way
...             I want it
...         '''))
>>> parser.print_help()
usage: PROG [-h]

Please do not mess up this text!
--------------------------------
   I have indented it
   exactly the way
   I want it

optional arguments:
 -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 [bar ...]]

positional arguments:
 bar         BAR! (default: [1, 2, 3])

optional arguments:
 -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

optional arguments:
  -h, --help  show this help message and exit
  --foo int
           

7、prefix_chars

許多指令行會使用 - 當作字首,比如 -f/–foo。如果解析器需要支援不同的或者額外的字元,比如像 +f 或者 /foo 的選項,可以在參數解析建構器中使用 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')
           

The prefix_chars= 參數預設使用 ‘-’. 支援一系列字元,但是不包括 - ,這樣會産生不被允許的 -f/–foo 選項。

8、fromfile_prefix_chars

當處理一個特别長的參數清單的時候,把它存入一個檔案中而不是在指令行打出來會很有意義。如果 fromfile_prefix_chars= 參數提供給 ArgumentParser 構造函數,之後所有類型的字元的參數都會被當成檔案處理,并且會被檔案包含的參數替代。舉個栗子:

>>> with open('args.txt', 'w') 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')
           

9、argument_default

一般情況下,參數預設會通過設定一個預設到 add_argument() 或者調用帶一組指定鍵值對的 ArgumentParser.set_defaults() 方法。但是有些時候,為參數指定一個普遍适用的解析器會更有用。這能夠通過傳輸 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()
           

10、allow_abbrev

正常情況下,當你向 ArgumentParser 的 parse_args() 方法傳入一個參數清單時,它會 recognizes abbreviations。

這個特性可以設定 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
           

還有add_argument()方法由于比較複雜會留到下個篇幅,近日更新

官網傳送:連結

繼續閱讀