python实现命令行解析的argparse的使用

参考https://docs.python.org/3.6/library/argparse.html

argparse模块使编写用户友好的命令行界面变得很容易。程序定义了它需要什么参数,argparse将找出如何从sys.argv中解析这些参数。argparse模块还自动生成帮助和使用消息,并在用户给程序提供无效参数时发出错误。

1.例子

下面的代码是一个Python程序,它接受一个整数列表,并产生和或最大值:

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的文件中,它可以在命令行运行,如果你没有输入任何参数,会报错:

(deeplearning) userdeMacBook-Pro:pytorch user$ python delete.py 
usage: delete.py [-h] [--sum] N [N ...]
delete.py: error: the following arguments are required: N

使用-h查看有用的帮助信息:

(deeplearning) userdeMacBook-Pro:pytorch user$ 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)

当使用适当的参数运行时,它输出命令行整数的和或最大值,默认得到的是最大值,添加--sum才指定计算的是和:

(deeplearning) userdeMacBook-Pro:pytorch user$ python prog.py 1 2 3 4
4
(deeplearning) userdeMacBook-Pro:pytorch user$ python prog.py 1 2 3 4 --sum
10

如果传入无效参数,则会发出错误:

(deeplearning) userdeMacBook-Pro:pytorch user$ python prog.py a b c
usage: prog.py [-h] [--sum] N [N ...]
prog.py: error: argument N: invalid int value: 'a'

下面的部分将带你了解这个示例。

1)创建一个parser

使用argparse的第一步是创建一个ArgumentParser对象:

>>> parser = argparse.ArgumentParser(description='Process some integers.')

该ArgumentParser对象将保存所有需要的信息去解析命令行到python数据类型中

2)添加参数

通过调用add_argument()方法,可以用关于程序参数的信息填充ArgumentParser。通常,这些调用告诉ArgumentParser如何获取命令行上的字符串并将它们转换成对象。当调用parse_args()时,将存储并使用此信息。例如:

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

稍后,调用parse_args()将返回一个具有整数和累加两个属性的对象。integers属性将是一个或多个int的列表,而累加属性将是sum()函数(如果--sum在命令行中指定),或者max()函数(如果没有制定--sum)。

3)解析参数

ArgumentParser通过parse_args()方法解析参数。这将检查命令行,将每个参数转换为适当的类型,然后调用适当的操作。在大多数情况下,这意味着一个简单的命名空间对象将建立从命令行解析的属性:

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

在脚本中,parse_args()通常没有参数,ArgumentParser将自动确定sys.argv中的命令行参数。

 parse_args()方法的返回值为namespace,可以用vars()内建函数化为字典

>>> args = parser.parse_args(['--sum', '7', '-1', '42'])
>>>args_dist = vars(args)
{'accumulate' : '[7, -1, 42]'}

 然后调用就可以使用args_dist['accumulate']

2.ArgumentParser对象及其参数

class argparse.ArgumentParser:

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)

创建一个新的ArgumentParser对象。所有参数都应该作为关键字参数传递。每一个参数都有其更详细的描述如下,但简而言之,它们是:

  • prog - 程序的名称 (default: sys.argv[0])
  • usage - 描述程序使用情况的字符串 (default: 从添加到解析器的参数生成)
  • description - 要在参数帮助信息前显示的文本 (default: none)
  • epilog - 要在参数帮助信息后显示的文本 (default: none)
  • parents - ArgumentParser对象的列表,其中也应该包含参数
  • formatter_class - 用于自定义帮助输出的类
  • prefix_chars - 用于前缀可选参数的字符集 (default: ‘-‘)
  • fromfile_prefix_chars - 前缀文件的一组字符,应从中读取附加参数 (default: None)
  • argument_default - 参数的全局默认值 (default: None)
  • conflict_handler - 解决选择冲突的策略 (usually unnecessary)
  • add_help - 添加-h/--help选项到解析器中 (default: True)
  • allow_abbrev - 允许长选项被缩写,如果缩写是明确的. (default: True)是3.5版本添加的参数

下面的部分将描述如何使用这些方法。

1)prog

默认情况下,ArgumentParser对象使用sys。以确定如何在帮助消息中显示程序的名称。这个缺省值几乎总是可取的,因为它将使帮助消息与在命令行上调用程序的方式匹配。例如,考虑一个名为myprogram.py的文件,其代码如下:

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

该程序的帮助将显示myprogram.py作为程序名,即sys.argv[0]的值(无论程序是从哪里调用的):

(deeplearning) userdeMacBook-Pro:argparse_learning user$ python myprogram.py --help
usage: myprogram.py [-h] [--foo FOO] #可见myprogram.py为程序名

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

(deeplearning) userdeMacBook-Pro:argparse_learning user$ cd ..

(deeplearning) userdeMacBook-Pro:pytorch user$ python argparse_learning/myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]

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

要更改此默认行为,可以使用prog= argument向ArgumentParser提供另一个值:

parser = argparse.ArgumentParser(prog = 'myprogram')

这样再运行可见返回的程序名就变成了myprogram

(deeplearning) userdeMacBook-Pro:pytorch user$ python myprogram.py --help
usage: myprogram [-h] [--foo FOO]

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

另一种查看方法是:

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

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

注意,由sys.argv[0]或prog= argument决定的程序名可以使用%(prog)s格式说明符来显示在帮助消息中:

>>> parse.add_argument('--foo', help='foo of the %(prog)s program') #添加参数是使用
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help='foo of the %(prog)s program', metavar=None)
>>> parse.print_help()
usage: myprogram [-h] [--foo FOO]

optional arguments:
  -h, --help  show this help message and exit
  --foo FOO   foo of the myprogram program
>>> 

2)usage

默认情况下,ArgumentParser从它包含的参数中计算使用消息:

>>> parse = argparse.ArgumentParser(prog = 'PROG')
>>> parse.add_argument('--foo', nargs='?', help='foo help')
_StoreAction(option_strings=['--foo'], dest='foo', nargs='?', const=None, default=None, type=None, choices=None, help='foo help', metavar=None)
>>> parse.add_argument('bar', nargs='+', help='bar help')
_StoreAction(option_strings=[], dest='bar', nargs='+', const=None, default=None, type=None, choices=None, help='bar help', metavar=None)
>>> parse.print_help()
usage: PROG [-h] [--foo [FOO]] bar [bar ...] #即这一行的消息可使用usage重写

positional arguments:
  bar          bar help

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

可以使用usage= keyword参数重写默认消息:

>>> parse = argparse.ArgumentParser(prog = 'PROG', usage='%(prog)s [option]')
>>> parse.add_argument('--foo', nargs='?', help='foo help')
_StoreAction(option_strings=['--foo'], dest='foo', nargs='?', const=None, default=None, type=None, choices=None, help='foo help', metavar=None)
>>> parse.add_argument('bar', nargs='+', help='bar help')
_StoreAction(option_strings=[], dest='bar', nargs='+', const=None, default=None, type=None, choices=None, help='bar help', metavar=None)
>>> parse.print_help()
usage: PROG [option]

positional arguments:
  bar          bar help

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

3)description

对ArgumentParser构造函数的大多数调用将使用description= keyword参数。这个参数简要描述了程序的功能及其工作原理。在帮助消息中,描述显示在命令行用法字符串和各种参数的帮助消息之间:

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

a foo that bars #显示在这里

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

默认情况下,描述description是行包装形式,以便适合给定的空间。要更改此行为,请参阅formatter_class参数,下面会说明。

4)epilog

有些程序喜欢在参数描述之后显示程序的附加描述。这样的文本可以使用epilog= argument指定ArgumentParser:

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

a foo that bars

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

And that's how you'd foo a bar

与description参数一样,默认情况下epilog= text是行包装的,但是可以使用formatter_class参数到ArgumentParser调整此行为。

5)formatter_class

ArgumentParser对象允许通过指定另一个格式化类来定制帮助格式化。目前有四类:

  • class argparse.RawDescriptionHelpFormatter
  • class argparse.RawTextHelpFormatter
  • class argparse.ArgumentDefaultsHelpFormatter
  • 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已经正确格式化,不应该换行:

补充:textwrap.dedent(text) 
这个方法是用来移除缩进

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

如果没有textwrap.dedent(text)。返回:

>>> parser = argparse.ArgumentParser(
...     prog='PROG',
...     formatter_class=argparse.RawDescriptionHelpFormatter,
...     description=''' 
...     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!')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=42, type=<class 'int'>, choices=None, help='FOO!', metavar=None)
>>> parser.add_argument('bar', nargs='*', default=[1, 2, 3], help='BAR!')
_StoreAction(option_strings=[], dest='bar', nargs='*', const=None, default=[1, 2, 3], type=None, choices=None, help='BAR!', metavar=None)
>>> 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为每个参数使用类型参数的名称作为其值的显示名称(而不是像常规格式化程序那样使用dest指明的显示名称):

>>> parser = argparse.ArgumentParser(
...     prog='PROG',
...     formatter_class=argparse.MetavarTypeHelpFormatter)
>>> parser.add_argument('--foo', type=int)
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)

#比如一般是使用dest='bar'中的bar作为显示名称,现在使用的是type=<class 'float'>中的float作为显示名称
>>> parser.add_argument('bar', type=float)
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=<class 'float'>, choices=None, help=None, metavar=None)

>>> parser.print_help()
usage: PROG [-h] [--foo int] float

positional arguments:
  float

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

6)parents

有时,几个解析器共享一组公共参数。与其重复这些参数的定义,不如使用一个包含所有共享参数并传递给parent = argument到ArgumentParser的单一解析器。parent = argument获取一个ArgumentParser对象列表,从其中收集所有的位置操作和可选操作,并将这些操作添加到正在构造的ArgumentParser对象中:

>>> parent_parser = argparse.ArgumentParser(add_help=False) #定义父解析器
>>> parent_parser.add_argument('--parent',type=int)
_StoreAction(option_strings=['--parent'], dest='parent', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)

>>> foo_parser  = argparse.ArgumentParser(parents=[parent_parser])
>>> foo_parser.add_argument('foo')
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
#测试传入的参数为'--parent', '2', 'XXX'时,得到的对应各个参数的值
>>> foo_parser.parse_args(['--parent', '2', 'XXX'])
Namespace(foo='XXX', parent=2)

>>> bar_parser = argparse.ArgumentParser(parents=[parent_parser])
>>> bar_parser.add_argument('--bar')
_StoreAction(option_strings=['--bar'], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> bar_parser.parse_args(['--bar', 'YYY'])
Namespace(bar='YYY', parent=None)

注意,大多数父解析器将指定add_help=False。否则,ArgumentParser将看到两个-h/--help选项(一个在父类中,一个在子类中),并引发一个错误。

在通过parent = 传递解析器之前,必须完全初始化它们。如果在子解析器之后更改父解析器,这些更改将不会反映在子解析器中

 看上面的例子可以看出,如果前面有写--bar类的标签,则其后面的参数就是这个标签对应的值,然后其后面的值就是其他的参数的值

7)prefix_chars

大多数命令行选项将使用-作为前缀,例如-f/--foo。需要支持不同或额外前缀字符的解析器,例如+f或/foo选项,可以使用ArgumentParser构造函数的prefix_chars= argument指定它们:

>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+')
>>> parser.add_argument('+f')
_StoreAction(option_strings=['+f'], dest='f', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('++bar')
_StoreAction(option_strings=['++bar'], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('+f X ++bar Y'.split())
Namespace(bar='Y', f='X')

prefix_chars=参数默认为'-'。提供一组不包含-的字符将导致-f/--foo选项被禁用。

8)fromfile_prefix_chars

有时,例如,当处理一个特别长的参数列表时,将参数列表保存在一个文件中,而不是在命令行中键入参数,可能是有意义的。如果将fromfile_prefix_chars=argument提供给ArgumentParser构造函数,那么以任何指定字符argument开头的参数都将被视为文件,并由它们包含的参数替换。例如:

>>> with open('args.txt', 'w') as fp:
...     fp.write('-f
bar')
... 
6  #返回文件内容的大小
>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
>>> parser.add_argument('-f')
_StoreAction(option_strings=['-f'], dest='f', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['-f', 'foo', '@args.txt'])
Namespace(f='bar')
>>> parser.parse_args(['-f', 'foo']) #如果没有使用上面的'@args.txt'返回的结果是
Namespace(f='foo')

默认情况下,从文件中读取的参数必须是每行一个(但也请参阅convert_arg_line_to_args()),并将其视为与在命令行中引用参数的原始文件位于同一位置。在上面的例子中,表达式['-f', 'foo', '@args。txt']被认为等同于表达式['-f', 'foo', '-f', 'bar']。

fromfile_prefix_chars=参数默认为None,这意味着参数永远不会被视为文件引用。

9)argument_default

通常,通过将默认值传递给add_argument()或使用一组特定的名称-值对调用set_defaults()方法来指定参数默认值。然而,有时为参数指定一个解析器范围的默认值可能很有用。这可以通过将argument_default=keyword 参数传递给ArgumentParser来实现。例如,为了全局地抑制parse_args()调用上的属性创建,我们提供argument_default= SUPPRESS:

>>> argparse.SUPPRESS
'==SUPPRESS=='
>>> parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
>>> parser.add_argument('--foo')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='==SUPPRESS==', type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('bar', nargs='?')
_StoreAction(option_strings=[], dest='bar', nargs='?', const=None, default='==SUPPRESS==', type=None, choices=None, help=None, metavar=None)

>>> parser.parse_args(['--foo', '1', 'BAR'])
Namespace(bar='BAR', foo='1')
>>> parser.parse_args([])
Namespace()

 提供default=argparse.SUPPRESS,如果命令行参数不存在,则不会添加任何属性,无默认值

10)allow_abbrev

通常,当你将参数列表传递给ArgumentParser的parse_args()方法时,它会识别长选项的缩写。

这个功能可以通过设置allow_abbrev为False来禁用:

>>> parser = argparse.ArgumentParser(prog='PROG', allow_abbrev=False)
>>> parser.add_argument('--foobar', action='store_true')
_StoreTrueAction(option_strings=['--foobar'], dest='foobar', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('--foonley', action='store_false')
_StoreFalseAction(option_strings=['--foonley'], dest='foonley', nargs=0, const=False, default=True, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['--foon'])
usage: PROG [-h] [--foobar] [--foonley]
PROG: error: unrecognized arguments: --foon

如果没有设置可见可以使用--foon缩写:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foobar', action='store_true')
_StoreTrueAction(option_strings=['--foobar'], dest='foobar', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('--foonley', action='store_false')
_StoreFalseAction(option_strings=['--foonley'], dest='foonley', nargs=0, const=False, default=True, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['--foon']) #因为这里没有设置--foobar所以返回false,如果设置应该为true
Namespace(foobar=False, foonley=False)

New in version 3.5.

11)conflict_handler

ArgumentParser对象不允许两个具有相同选项字符串的操作。默认情况下,如果使用已经使用的选项字符串创建参数,ArgumentParser对象会引发异常:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-f', '--foo', help='old foo help')
_StoreAction(option_strings=['-f', '--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help='old foo help', metavar=None)
>>> parser.add_argument('--foo', help='new foo help')
Traceback (most recent call last):
...  
File "/anaconda3/envs/deeplearning/lib/python3.6/argparse.py", line 1514, in _handle_conflict_error
    raise ArgumentError(action, message % conflict_string)
argparse.ArgumentError: argument --foo: conflicting option string: --foo

有时(例如,当使用父类时),简单地用相同的选项字符串覆盖任何旧的参数可能是有用的。要获得这种行为,可以将值'resolve'提供给ArgumentParser的conflict_handler= argument

即如果你想要覆盖操作实现而不是报错:

>>> parser = argparse.ArgumentParser(prog='PROG', conflict_handler='resolve')
>>> parser.add_argument('-f', '--foo', help='old foo help')
_StoreAction(option_strings=['-f', '--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help='old foo help', metavar=None)
>>> parser.add_argument('--foo', help='new foo help')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help='new foo help', metavar=None)
>>> parser.print_help()
usage: PROG [-h] [-f FOO] [--foo FOO]

optional arguments:
  -h, --help  show this help message and exit
  -f FOO      old foo help
  --foo FOO   new foo help

注意ArgumentParser对象只有在其所有选项字符串都被覆盖时才删除操作。因此,在上面的示例中,旧的-f/--foo操作保留为-f操作,因为只覆盖了--foo选项字符串。

即你调用-f是执行的是old foo help, --foo时执行的是new foo help

12)add_help

默认情况下,ArgumentParser对象会添加一个选项,该选项只显示解析器的帮助消息。例如,考虑一个名为myprogram.py的文件,其中包含以下代码:

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

如果在命令行中提供-h或--help,将打印ArgumentParser help:

(deeplearning) userdeMacBook-Pro:argparse_learning user$ python myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]

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

有时,禁用此帮助选项的添加可能很有用。这可以通过将False作为add_help=argument传递给ArgumentParser来实现:

>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)
>>> parser.add_argument('--foo', help='foo help')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help='foo help', metavar=None)
>>> parser.print_help()
usage: PROG [--foo FOO]

optional arguments:
  --foo FOO  foo help

help选项通常是-h/--help。例外情况是,如果指定了前缀prefix_chars,使前缀不包含-,在这种情况下-h和--help都不是有效的选项。在本例中,prefix_chars中的第一个字符用于为帮助选项添加前缀:

>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='+/')
>>> parser.print_help()
usage: PROG [+h]

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

3.add_argument()方法及其参数

ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])

定义如何解析单个命令行参数。每个参数在下面都有自己更详细的描述:

  • name or flags - 名称或选项字符串列表, e.g. foo or -f, --foo.
  • action - 在命令行中遇到此参数时要采取的基本操作类型.
  • nargs - 应该使用的命令行参数的数量.
  • const - 某些操作和nargs选择所需的常量.
  • default - 如果参数不在命令行中,则生成的默认值.
  • type - 应将命令行参数转换为的类型.
  • choices - 参数的允许值的容器.
  • required - 是否可以省略命令行选项 (只可选).
  • help - 简单描述一下这个参数的作用.
  • metavar - usage消息中参数的名称.
  • dest - 要添加到parse_args()返回的对象中的属性的名称

下面的部分将描述如何使用这些方法。

1)name or flags

add_argument()方法必须知道是否需要一个可选参数,比如-f或--foo,或者一个位置参数,比如文件名列表。因此,传递给add_argument()的第一个参数必须是一系列标志,或者是一个简单的参数名。例如,可以创建一个可选参数,如下所示:

一系列标志:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-f', '--foo')
_StoreAction(option_strings=['-f', '--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

或一个简单的参数名:

>>> parser.add_argument('bar')
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

2)action

ArgumentParser对象将命令行参数与操作关联起来。这些操作可以对与之关联的命令行参数执行任何操作,尽管大多数操作只是向parse_args()返回的对象添加一个属性。action关键字参数指定应该如何处理命令行参数。所提供的操作如下:

  • 'store' - 它只存储参数的值。这是默认操作,即不用特殊指定。例如:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo') #默认action='store'
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('--foo 1'.split())
Namespace(foo='1')
  • 'store_const' - 它存储由const关键字参数指定的值。“store_const”操作通常与指定某种标志的可选参数一起使用,如const=。将参数设置为某常量值。例如:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_const', const=42)
_StoreConstAction(option_strings=['--foo'], dest='foo', nargs=0, const=42, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['--foo'])
Namespace(foo=42)

⚠️不能写成:

>>> parser.parse_args('--foo')
usage: [-h] [--foo]
: error: unrecognized arguments: - - f o o
  • 'store_true' and 'store_false' - 这些是'store_const'的特殊情况,分别用于存储值True和False。此外,它们分别创建False和True的默认值。例如:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_true')
_StoreTrueAction(option_strings=['--foo'], dest='foo', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('--bar', action='store_false')
_StoreFalseAction(option_strings=['--bar'], dest='bar', nargs=0, const=False, default=True, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('--baz', action='store_false')
_StoreFalseAction(option_strings=['--baz'], dest='baz', nargs=0, const=False, default=True, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('--foo --bar --baz'.split())
Namespace(bar=False, baz=False, foo=True)

如果你没有设置解析--foo,其返回值会是false:

>>> parser.parse_args('--bar --baz'.split())
Namespace(bar=False, baz=False, foo=False)
  • 'append' -它存储一个列表,并将每个参数值附加到列表中。这对于允许多次指定某个选项非常有用。使用示例:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='append')
_AppendAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('--foo 1 --foo 2'.split())
Namespace(foo=['1', '2'])
  • 'append_const' - 它存储一个列表,并将const关键字参数指定的值附加到列表中。(注意const关键字参数默认为None。)当多个参数需要将常量存储到同一个列表中时,“append_const”操作通常非常有用。例如:
>>> parser = argparse.ArgumentParser()
#dest='types'使得使用parse_args()时该值的返回参数名为Namespace(types=...)
>>> parser.add_argument('--str', dest='types', action='append_const', const=str) 
_AppendConstAction(option_strings=['--str'], dest='types', nargs=0, const=<class 'str'>, default=None, type=None, choices=None, help=None, metavar=None)

>>> parser.add_argument('--int', dest='types', action='append_const', const=int) 
_AppendConstAction(option_strings=['--int'], dest='types', nargs=0, const=<class 'int'>, default=None, type=None, choices=None, help=None, metavar=None)

#从返回可见这两个const值会被一起存储在一个列表中
>>> parser.parse_args('--str --int'.split())
Namespace(types=[<class 'str'>, <class 'int'>])
>>> parser.print_help()
usage: [-h] [--str] [--int]

optional arguments:
  -h, --help  show this help message and exit
  --str
  --int
  • 'count' - 这将计算关键字参数出现的次数。例如,这对于增加冗长程度很有用:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--verbose', '-v', action='count')
_CountAction(option_strings=['--verbose', '-v'], dest='verbose', nargs=0, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['-vvv'])
Namespace(verbose=3)
  • 'help' - 这将为当前解析器中的所有选项打印完整的帮助消息,然后退出。默认情况下,帮助操作会自动添加到解析器中。有关如何创建输出的详细信息,请参见ArgumentParser。

  • 'version' - 这需要在add_argument()调用中使用version= keyword参数,并在调用时打印version信息并退出:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--version', action='version', version='%(prog)s 2.0')
_VersionAction(option_strings=['--version'], dest='version', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help="show program's version number and exit", metavar=None)
>>> parser.parse_args(['--version'])
PROG 2.0
(deeplearning) userdeMacBook-Pro:pytorch-learning user$ 

还可以通过传递实现相同接口的action子类或其他对象来指定任意操作。推荐的方法是扩展Action,覆盖__call__方法和可选的__init__方法。

自定义action操作的一个例子:

>>> import argparse
>>> class FooAction(argparse.Action):
...     def __init__(self, option_strings, dest, nargs=None, **kwargs):
...             if nargs is not None:
...                     raise ValueError("nargs not allowed")
...             super(FooAction, self).__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)
FooAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('bar', action=FooAction)
FooAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

>>> args = parser.parse_args('1 --foo 2'.split()) #等价于输入['1', '--foo', '2']
Namespace(bar=None, foo=None) '1' None #可见这里是先将1赋值给bar
Namespace(bar='1', foo=None) '2' '--foo' #然后将输入'--foo'作为option_string,并将2赋值给foo
>>> args
Namespace(bar='1', foo='2')

For more details, see Action.即下面的Action classes

Action classes

Action类实现Action API,一个可调用的API返回一个可调用的API,该API处理命令行中的参数。任何遵循此API的对象都可以作为action参数传递给add_argument()。

class argparse.Action

class argparse.Action(option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, metavar=None)

ArgumentParser使用Action对象来表示从命令行中的一个或多个字符串解析单个参数所需的信息。Action类必须接受两个位置参数以及传递给ArgumentParser.add_argument()的关键字参数(除了Action本身)。

Action实例(或任何可调用Action参数的返回值)应该定义属性“dest”、“option_string”、“default”、“type”、“required”、“help”等。确保定义这些属性的最简单方法是调用Action.__init__。

Action实例应该是可调用的,因此子类必须覆盖__call__方法,该方法应该接受四个参数:

  • parser - 包含此操作的ArgumentParser对象.
  • namespace - 将由parse_args()返回的名称空间对象。大多数操作使用setattr()向该对象添加属性.
  • values - 关联的命令行参数,以及应用的任何类型转换。类型转换由type关键字参数指定给add_argument().
  • option_string -  用于调用此操作的选项字符串,即带--的。option_string参数是可选的,如果操作与位置参数关联,则该参数将不存在.

__call__方法可以执行任意操作,但通常会基于dest和值在名称空间上设置属性。

3)nargs

ArgumentParser对象通常将一个命令行参数与一个要执行的操作关联起来。nargs关键字参数将不同数量的命令行参数与一个操作关联起来。支持的值是:

  • N(整数):命令行中的N个参数将被收集到一个列表中。例如:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs=2) #指明其需要两个参数
_StoreAction(option_strings=['--foo'], dest='foo', nargs=2, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('bar', nargs=1) #指明需要一个参数
_StoreAction(option_strings=[], dest='bar', nargs=1, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('c --foo a b'.split())
Namespace(bar=['c'], foo=['a', 'b'])

注意,nargs=1生成一个包含一项的列表。这与默认值不同,默认值中项目是由自己生成的。

  • ' ? ':如果可能,一个参数将从命令行中使用,并作为单个项目生成。如果不存在命令行参数,则会生成默认值。注意,对于可选参数,还有另外一种情况——出现了选项字符串,但后面没有命令行参数。即可以接受0个或1个参数。在本例中,将生成来自const的值,在解析命令行时,如果遇到选项字符串后面没有命令行参数,即0个参数,那么将使用const的值。一些例子可以说明这一点:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs='?', const='c', default='d')
_StoreAction(option_strings=['--foo'], dest='foo', nargs='?', const='c', default='d', type=None, choices=None, help=None, metavar=None)

>>> parser.add_argument('bar', nargs='?', default='d')
_StoreAction(option_strings=[], dest='bar', nargs='?', const=None, default='d', type=None, choices=None, help=None, metavar=None)

>>> 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='?'最常见的用法之一是是允许可选的输入和输出文件:

>>> import argparse, sys
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
_StoreAction(option_strings=[], dest='infile', nargs='?', const=None, default=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>, type=FileType('r'), choices=None, help=None, metavar=None)
>>> parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
_StoreAction(option_strings=[], dest='outfile', nargs='?', const=None, default=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>, type=FileType('w'), choices=None, help=None, metavar=None)

#此时当前目录下必须有文件input.txt,运行完后会在当前目录生成output.txt文件
>>> parser.parse_args(['input.txt', 'output.txt'])
Namespace(infile=<_io.TextIOWrapper name='input.txt' mode='r' encoding='UTF-8'>, outfile=<_io.TextIOWrapper name='output.txt' mode='w' encoding='UTF-8'>)

>>> parser.parse_args([])
Namespace(infile=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>, outfile=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>)
  • '*' : 所有当前的命令行参数都被收集到一个列表中。注意,使用多个nargs='*'的位置参数通常没有多大意义,但是使用nargs='*'的多个可选参数是可能的,即可以使用0个或多个参数。例如:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs='*')
_StoreAction(option_strings=['--foo'], dest='foo', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('--bar', nargs='*')
_StoreAction(option_strings=['--bar'], dest='bar', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('baz', nargs='*')
_StoreAction(option_strings=[], dest='baz', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('a b --foo x y --bar 1 2'.split())
Namespace(bar=['1', '2'], baz=['a', 'b'], foo=['x', 'y'])
>>> parser.parse_args('a b --foo x --bar'.split())
Namespace(bar=[], baz=['a', 'b'], foo=['x'])
  • '+' : 就像'*'一样,所有的命令行arg都被收集到一个列表中。不同在于,如果没有至少一个命令行参数,将生成错误消息,即接受1个或多个参数。例如:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('foo', nargs='+')
_StoreAction(option_strings=[], dest='foo', nargs='+', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> 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
  • argparse.REMAINDER : 所有剩余的命令行参数都被收集到一个列表中。这对于调度到其他命令行实用程序的命令行实用程序通常很有用:
>>> import argparse
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

>>> parser.add_argument('command')
_StoreAction(option_strings=[], dest='command', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

>>> parser.add_argument('args', nargs=argparse.REMAINDER) #会将其他参数以外的其他参数当作自己的参数
_StoreAction(option_strings=[], dest='args', nargs='...', const=None, default=None, type=None, choices=None, help=None, metavar=None)

>>> parser.parse_args('--foo B cmd --arg1 XX zz'.split())
Namespace(args=['--arg1', 'XX', 'zz'], command='cmd', foo='B')

如果没有提供nargs关键字参数,则使用的参数数量由action决定。通常,这意味着将使用一个命令行参数,并生成一个项目(而不是列表)。

4)const

 add_argument()的const参数用于保存常量,这些常量不是从命令行读取的,而是用于各种ArgumentParser操作。它最常见的两个用途是:

  • 当使用action='store_const'或action='append_const'调用add_argument()时。这些操作将const值添加到parse_args()返回的对象的一个属性中。上面介绍action时有使用到
  • 当使用选项字符串(如-f或--foo)和nargs='?'调用add_argument()时。这将创建一个可选参数,后面可以跟着零个或一个命令行参数。在解析命令行时,如果遇到选项字符串后面没有命令行参数,那么将使用const的值。有关示例,请参见nargs描述。

对于“store_const”和“append_const”操作,必须给出const关键字参数。对于其他操作,默认为None。

5)default

所有可选参数和一些位置参数都可以在命令行中省略。add_argument()的default关键字参数的值默认为None,它指定如果命令行参数不存在,应该使用什么值。对于可选参数,在命令行不存在选项字符串时使用默认值:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default=42)
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=42, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['--foo', '2'])
Namespace(foo='2')
>>> parser.parse_args([])
Namespace(foo=42)

如果默认值是字符串,则解析器将解析该值,就像解析命令行参数一样。特别是,在设置Namespace返回值的属性之前,如果提供了类型转换参数,解析器将应用任何类型转换参数。否则,解析器将使用如下值:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--length', default='10', type=int)
_StoreAction(option_strings=['--length'], dest='length', nargs=None, const=None, default='10', type=<class 'int'>, choices=None, help=None, metavar=None)
>>> parser.add_argument('--width', default=10.5, type=int)
_StoreAction(option_strings=['--width'], dest='width', nargs=None, const=None, default=10.5, type=<class 'int'>, choices=None, help=None, metavar=None)
>>> parser.parse_args()
Namespace(length=10, width=10.5)

对于带有nargs等于?或*的位置参数,当没有命令行参数时使用default默认值:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('foo', nargs='?', default=42)
_StoreAction(option_strings=[], dest='foo', nargs='?', const=None, default=42, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['a'])
Namespace(foo='a')
>>> parser.parse_args([])
Namespace(foo=42)

提供default=argparse.SUPPRESS,如果命令行参数不存在,则不会添加任何属性,无默认值:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default=argparse.SUPPRESS)
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='==SUPPRESS==', type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args([])
Namespace()
>>> parser.parse_args(['--foo', '1'])
Namespace(foo='1')

6)type

默认情况下,ArgumentParser对象以简单字符串的形式读取命令行参数。然而,命令行字符串通常应该被解释为另一种类型,比如float或int。add_argument()的type关键字参数允许执行任何必要的类型检查和类型转换。常见的内置类型和函数可以直接用作type参数的值:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('foo', type=int)
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)
>>> parser.add_argument('bar', type=open)
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=<built-in function open>, choices=None, help=None, metavar=None)
>>> parser.parse_args('2 input.txt'.split())
Namespace(bar=<_io.TextIOWrapper name='input.txt' mode='r' encoding='UTF-8'>, foo=2)

有关类型参数何时应用于默认参数的信息,请参阅上面default关键字参数一节。

为了方便使用各种类型的文件,argparse模块提供了工厂FileType,它接受open()函数的mode=、bufsize=、encoding=和errors=arguments。例如,FileType('w')可以用来创建一个可写文件:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('bar', type=argparse.FileType('w'))
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=FileType('w'), choices=None, help=None, metavar=None)
>>> parser.parse_args(['output.txt'])
Namespace(bar=<_io.TextIOWrapper name='output.txt' mode='w' encoding='UTF-8'>)

type=可以接受任何接受单个字符串参数并返回转换值的可调用值:

>>> def perfect_square(string): #判断string是否能够平方根后返回一个整数
...     value = int(string)
...     sqrt = math.sqrt(value)
...     if sqrt != int(sqrt):
...             msg = "%r is not a perfect square" %string
...             raise argparse.ArgumentTypeError(msg)
...     return value
... 
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('foo', type=perfect_square)
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=<function perfect_square at 0x1018b47b8>, choices=None, help=None, metavar=None)
>>> parser.parse_args(['9']) #该传入的值将作为perfect_square的参数值string,返回值将作为foo的值
Namespace(foo=9)
>>> parser.parse_args(['7'])
usage: PROG [-h] foo
PROG: error: argument foo: '7' is not a perfect square

See the choices section for more details.即下面

7)choices

应该从一组受限制的值中选择一些命令行参数。可以通过将容器对象作为choice关键字参数传递给add_argument()来处理这些问题。当解析命令行时,将检查参数值,如果参数不是可接受的值之一,将显示错误消息:

>>> import argparse
>>> parser = argparse.ArgumentParser(prog='game.py')
>>> parser.add_argument('move', choices=['rock', 'paper', 'scissors'])
_StoreAction(option_strings=[], dest='move', nargs=None, const=None, default=None, type=None, choices=['rock', 'paper', 'scissors'], help=None, metavar=None)
>>> parser.parse_args(['rock'])
Namespace(move='rock')
>>> parser.parse_args(['fire']) #不是choices里面的值,将会返回错误
usage: game.py [-h] {rock,paper,scissors}
game.py: error: argument move: invalid choice: 'fire' (choose from 'rock', 'paper', 'scissors')

注意,在执行任何类型转换之后,都会检查choices容器中的内容,因此choices容器中的对象的类型应该与指定的type类型匹配:

>>> import argparse
>>> parser = argparse.ArgumentParser(prog='doors.py')
>>> parser.add_argument('door', type=int, choices=range(1,4))
_StoreAction(option_strings=[], dest='door', nargs=None, const=None, default=None, type=<class 'int'>, choices=range(1, 4), help=None, metavar=None)
>>> parser.parse_args(['3'])
Namespace(door=3)
>>> parser.parse_args(['4'])
usage: doors.py [-h] {1,2,3}
doors.py: error: argument door: invalid choice: 4 (choose from 1, 2, 3)

任何支持in操作符的对象都可以作为choices传递,因此dict对象、set对象、定制容器等都是受支持的。

8)required

通常,argparse模块假设-f和--bar等标志表示可选参数,这些参数在命令行中总是可以省略。要使选项成为必需的,可以为required= keyword参数指定True,然后将其指定为add_argument():

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', required=True)
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['--foo', 'BAR'])
Namespace(foo='BAR')
>>> parser.parse_args([]) #必须要有--foo,不然报错
usage: [-h] --foo FOO
: error: the following arguments are required: --foo

如示例所示,如果一个选项被标记为required,那么如果该选项不在命令行中,parse_args()将报告一个错误。

⚠️必需选项通常被认为是不好的形式,因为用户希望选项是可选的,因此应该尽可能避免使用它们

9)help

help值是一个字符串,包含参数的简短描述。当用户请求帮助(通常在命令行使用-h或--help)时,这些帮助描述将与每个参数一起显示:

>>> import argparse
>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('--foo', action='store_true', help='foo the bars before frobbling')
_StoreTrueAction(option_strings=['--foo'], dest='foo', nargs=0, const=True, default=False, type=None, choices=None, help='foo the bars before frobbling', metavar=None)
>>> parser.add_argument('bar', nargs='+' , help='one of the bars to be frobbled')
_StoreAction(option_strings=[], dest='bar', nargs='+', const=None, default=None, type=None, choices=None, help='one of the bars to be frobbled', metavar=None)
>>> parser.parse_args(['-h'])
usage: frobble [-h] [--foo] bar [bar ...]

positional arguments:
  bar         one of the bars to be frobbled

optional arguments:
  -h, --help  show this help message and exit
  --foo       foo the bars before frobbling

help字符串可以包含各种格式说明符,以避免重复程序名或参数默认值等内容。可用的说明符包括程序名、%(prog)s和add_argument()的大多数关键字参数,例如%(default)s获取默认值、%(type)s获取类型值等:

>>> import argparse
>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('bar', nargs='?', type=int, default=42, help='the bar to %(prog)s (default: %(default)s)')
_StoreAction(option_strings=[], dest='bar', nargs='?', const=None, default=42, type=<class 'int'>, choices=None, help='the bar to %(prog)s (default: %(default)s)', metavar=None)
>>> parser.print_help()
usage: frobble [-h] [bar]

positional arguments:
  bar         the bar to frobble (default: 42)

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

由于help字符串支持%-格式化,如果希望帮助字符串中出现文字%,则必须将其转义为%%。

通过将help值设置为argparse.SUPPRESS, argparse支持对某些选项禁用help条目:

>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('--foo', help=argparse.SUPPRESS)
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help='==SUPPRESS==', metavar=None)
>>> parser.print_help()
usage: frobble [-h]

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

没有禁用的输出是:

>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('--foo')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.print_help()
usage: frobble [-h] [--foo FOO]

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

10)metavar:定义期望参数的名字

当ArgumentParser生成help消息时,它需要某种方法来引用每个期望的参数。默认情况下,ArgumentParser对象使用dest值作为每个对象的“名称”。默认情况下,对于位置参数操作,dest值直接使用,对于可选参数操作,dest值大写。因此,一个位置参数dest='bar'将被称为bar。一个可选参数--foo,后面应该跟着一个命令行参数,该命令行参数将被称为FOO。

一个例子:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('bar')
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('X --foo Y'.split())
Namespace(bar='X', foo='Y')
>>> parser.print_help()
usage: [-h] [--foo FOO] bar

positional arguments:
  bar

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

可使用metavar指定替代名称:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', metavar='YYY')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar='YYY')
>>> parser.add_argument('bar', metavar='XXX')
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, 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

optional arguments:
  -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) #不使用metavar,则help参数名默认为其大写
_StoreAction(option_strings=['-x'], dest='x', nargs=2, const=None, default=None, type=None, choices=None, help=None, metavar=None)

>>> parser.add_argument('--foo', nargs=2, metavar=('bar', 'baz'))
_StoreAction(option_strings=['--foo'], dest='foo', nargs=2, const=None, default=None, type=None, choices=None, help=None, metavar=('bar', 'baz'))
>>> parser.print_help()
usage: PROG [-h] [-x X X] [--foo bar baz]

optional arguments:
  -h, --help     show this help message and exit
  -x X X
  --foo bar baz

11)dest:决定parse_args()对象上的属性名称

大多数ArgumentParser动作都会添加一些值作为parse_args()返回的对象的属性。此属性的名称由add_argument()的dest关键字参数决定。

对于位置参数操作,dest通常作为add_argument()的第一个参数提供:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('bar') #位置参数
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['XXX'])
Namespace(bar='XXX')

对于可选参数操作,dest的值通常从选项字符串推断。

推断顺序:

  • ArgumentParser通过获取第一个长选项字符串并去掉初始 -- 字符串来生成dest的值,如下面的--foo的dest值为foo
  • 如果没有提供长选项字符串,dest将从第一个短选项字符串中去掉初始的-字符来提取值,如下面的-x的dest值为x。

任何内部-字符将被转换为_字符,以确保字符串是一个有效的属性名,如下面的--foo-bar的dest名为foo_bar

下面的例子说明了这种行为:

>>> parser = argparse.ArgumentParser()
#你调用'-f', '--foo-bar', '--foo'任何之一的效果都是一样的,只是在parse_args()中显示的名字都是dest的值
>>> parser.add_argument('-f', '--foo-bar', '--foo')
_StoreAction(option_strings=['-f', '--foo-bar', '--foo'], dest='foo_bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
#你调用'-x', '-y'任何之一的效果都是一样的,只是在parse_args()中显示的名字都是dest的值
>>> parser.add_argument('-x', '-y')
_StoreAction(option_strings=['-x', '-y'], dest='x', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> 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')
>>> parser.print_help()
usage: [-h] [-f FOO_BAR] [-x X]

optional arguments:
  -h, --help            show this help message and exit
  -f FOO_BAR, --foo-bar FOO_BAR, --foo FOO_BAR
  -x X, -y X

dest允许提供自定义属性名:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', dest='bar') #自定义名为'bar'
_StoreAction(option_strings=['--foo'], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('--foo XXX'.split())
Namespace(bar='XXX')

4.parse_args()方法

ArgumentParser.parse_args(args=None, namespace=None)

将参数字符串转换为对象,并将它们指定为名称空间的属性。返回填充的名称空间。

之前对add_argument()的调用确定了创建什么对象以及如何分配对象。有关详细信息,请参阅上面add_argument()的介绍。

  • args - 要解析的字符串列表。默认值取自sys.argv.
  • namespace - 获取属性的对象。默认值是一个新的空名称空间对象.

举例:

>>> class C: #声明一个对象用作namespace对象
...     pass
... 
>>> c = C()
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(args=['--foo', 'BAR'], namespace=c) #这样这里就不会使用新的namespace对象了
<__main__.C object at 0x10baf6a20>
>>> c.foo
'BAR'

1)可选值语法

parse_args()方法支持几种指定选项值的方法(如果接受一种方法)。

1> 在最简单的情况下,该选项及其值作为两个单独的参数传递:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x')
_StoreAction(option_strings=['-x'], dest='x', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('--foo')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['-x', 'X'])
Namespace(foo=None, x='X')
>>> parser.parse_args(['--foo', 'FOO'])
Namespace(foo='FOO', x=None)

2>对于长选项(名称大于单个字符的选项),也可以将选项和值作为单个命令行参数传递,使用=分隔它们:

>>> parser.parse_args(['--foo=FOO'])
Namespace(foo='FOO', x=None)

3>对于较短的选项(选项只有一个字符长),可以将该选项及其值连接起来:

>>> parser.parse_args(['-xX'])
Namespace(foo=None, x='X')

4>几个短选项可以连接在一起,只使用一个前缀,只要只有最后一个选项(或没有一个选项)需要一个值:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x', action='store_true')
_StoreTrueAction(option_strings=['-x'], dest='x', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('-y', action='store_true')
_StoreTrueAction(option_strings=['-y'], dest='y', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('-z')
_StoreAction(option_strings=['-z'], dest='z', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['-xyzZ'])
Namespace(x=True, y=True, z='Z')

2)无效参数

在解析命令行时,parse_args()检查各种错误,包括不明确的选项、无效类型、无效选项、错误的位置参数数量等。当它遇到这样的错误时,它会退出并打印错误以及使用信息:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', type=int)
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)
>>> parser.add_argument('bar', nargs='?')
_StoreAction(option_strings=[], dest='bar', nargs='?', const=None, default=None, type=None, choices=None, help=None, metavar=None)

1>期待值类型为int,传入类型为string

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

2>输入无效的option

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', type=int)
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)
>>> parser.add_argument('bar', nargs='?')
_StoreAction(option_strings=[], dest='bar', nargs='?', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['--bar'])
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: unrecognized arguments: --bar

3>输入参数的数量有误,这里的参数会作为bar的参数,但是bar只接受0或1个参数

>>> parser.parse_args(['spam','badger'])
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: unrecognized arguments: badger

3)包含-的参数

parse_args()方法尝试在用户明显犯了错误时给出错误,但是有些情况本质上是模棱两可的。

例如,命令行参数-1可以是指定选项的尝试,也可以是提供位置参数的尝试。parse_args()方法在这里很谨慎:如果它们看起来像负数,位置参数可能从-开始,并且解析器中没有看起来像负数的选项,即以-开头的选项,那么:

1> 不带负数选项的例子:

>>> import argparse
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x')
_StoreAction(option_strings=['-x'], dest='x', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('foo', nargs='?')
_StoreAction(option_strings=[], dest='foo', nargs='?', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('-x', '-1')

因为没有负数选项,所以-1会被当作位置参数,而不是以-开头的选项:

>>> parser.parse_args(['-x', '-1'])
Namespace(foo=None, x='-1')

因为没有负数选项,所以-1,-5会被当作位置参数:

>>> parser.parse_args(['-x', '-1', '-5'])
Namespace(foo='-5', x='-1')

2》 带负数选项的例子

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('foo', nargs='?')
_StoreAction(option_strings=[], dest='foo', nargs='?', const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('-1', dest='one')
_StoreAction(option_strings=['-1'], dest='one', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

因为带负数选项-1,所有-1会被当作选项而不是参数:

>>> parser.parse_args(['-1', 'X'])
Namespace(foo=None, one='X')

因为有负数选项,因此'-2'没有被当成'foo'参数,而是当成一个选项,所以报没有这个选项的错:

>>> parser.parse_args(['-2'])
usage: PROG [-h] [-1 ONE] [foo]
PROG: error: unrecognized arguments: -2

这样两个'-1'都会被当成选项,所以会报没有参数的错:

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

这样'-f'就会被当成'foo'的参数

4)参数缩写(前缀匹配)

默认情况下,parse_args()方法允许将长选项缩写为前缀,如果缩写没有歧义(前缀匹配唯一选项):

即下面的例子中,'-bacon'可以缩写成'-bac',不能缩写成'ba',因为这样不能区分说的是'badger'还是'bacon'

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-bacon')
_StoreAction(option_strings=['-bacon'], dest='bacon', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('-badger')
_StoreAction(option_strings=['-badger'], dest='badger', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> 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 -bacon, -badger

对于可能产生多个选项的参数会产生错误。

可以通过将allow_abbrev设置为False禁用此特性。

5)除了 sys.argv

有时候,使用ArgumentParser解析sys.argv之外的参数可能很有用。这可以通过将字符串列表传递给parse_args()来实现。这对于在交互提示符下进行测试非常有用:

>>> import argparse
>>> parser = argparse.ArgumentParser()
#得到数字的最大值
>>> parser.add_argument('integers', metavar='int', type=int, choices=range(10), nargs='+', help='an integer in the range 0..9')
_StoreAction(option_strings=[], dest='integers', nargs='+', const=None, default=None, type=<class 'int'>, choices=range(0, 10), help='an integer in the range 0..9', metavar='int')
#得到数字的和
>>> parser.add_argument('--sum', dest='accumulate', action='store_const', const=sum, default=max, help='sum the integers (default: find the max)')
_StoreConstAction(option_strings=['--sum'], dest='accumulate', nargs=0, const=<built-in function sum>, default=<built-in function max>, type=None, choices=None, help='sum the integers (default: find the max)', metavar=None)
#默认使用的是求最大值,只有使用--sum指明使用的是求和
>>> 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])

>>> parser.print_help()
usage: [-h] [--sum] int [int ...]

positional arguments:
  int         an integer in the range 0..9

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

6)Namespace对象

class argparse.Namespace
  • parse_args()默认情况下使用Simple类创建一个包含属性的对象并返回它。

这个类非常简单,只是一个带有可读字符串表示的对象子类。如果你希望属性具有类似于词典的视图,可以使用标准Python习语vars():

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> args = parser.parse_args(['--foo', 'BAR']) #将属性分配给新的namespace对象
>>> args
Namespace(foo='BAR')
>>> vars(args)
{'foo': 'BAR'}

让ArgumentParser将属性分配给一个已经存在的对象,而不是一个新的namespace对象,这可能也很有用。这可以通过指定namespace= keyword参数来实现:

>>> class C:
...     pass
... 
>>> c = C()
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(args=['--foo', 'BAR'], namespace=c)
<__main__.C object at 0x10baf6a20>
>>> c.foo
'BAR'

5.其他功能

1)Sub-commands子命令

ArgumentParser.add_subparsers([title][, description][, prog][, parser_class][, action][, option_string][, dest][, help][, metavar])

许多程序将其功能分解为许多子命令,例如,svn程序可以调用svn checkout、svn update和svn commit等子命令。

当一个程序执行几个不同的函数,而这些函数又需要不同类型的命令行参数时,以这种方式分割功能可能是一个特别好的主意。ArgumentParser支持使用add_subparsers()方法创建这样的子命令。

add_subparsers()方法通常不带参数调用,并返回一个特殊的操作对象。

这个对象只有一个方法add_parser(),它接受命令名和任何ArgumentParser构造函数参数,并返回一个可以像往常一样修改的ArgumentParser对象。

参数描述:

  • title - help输出中子解析器组的标题;默认情况下,如果提供description的值,则使用“subcommands”,否则使用title作为位置参数
  • description - help输出中的子解析器组的description,默认情况下为None
  • prog - 子命令help将显示的usage信息,默认情况下是程序的名称和子解析器参数之前的任何位置参数
  • parser_class - 类,该类将用于创建子解析器实例,默认情况下为当前解析器的类 (e.g. ArgumentParser)
  • action - 在命令行中遇到此参数时要采取的基本操作类型
  • dest - 将存储子命令名的属性的名称;默认情况下,不存储任何值
  • help - help输出中的子解析器组的help,默认情况下为None
  • metavar - 在help中显示可用子命令的字符串;默认情况下,它是None,并以{cmd1, cmd2, ..}的形式显示子命令。

举例说明:

#创建一个顶级的解析器
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', action='store_true', help='foo help')
_StoreTrueAction(option_strings=['--foo'], dest='foo', nargs=0, const=True, default=False, type=None, choices=None, help='foo help', metavar=None)

#在该顶级解析器基础上生成一个子解析器对象
>>> subparsers = parser.add_subparsers(help='sub-command help')

#然后使用该子解析器对象生成一个名为'a'的解析器,并为其添加参数
>>> parser_a = subparsers.add_parser('a', help='a help')
>>> parser_a.add_argument('bar', type=int, help='bar help')
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help='bar help', metavar=None)

#然后又使用该子解析器对象生成另一个名为'b'的解析器,并为其添加参数
>>> parser_b = subparsers.add_parser('b', help='b help')
>>> parser_b.add_argument('--baz', choices='XYZ', help='baz help')
_StoreAction(option_strings=['--baz'], dest='baz', nargs=None, const=None, default=None, type=None, choices='XYZ', help='baz help', metavar=None)
#a,b两个解析器是相互独立的

#声明是为解析器a传参
>>> parser.parse_args(['a', '12'])
Namespace(bar=12, foo=False)

#设置父解析器的'--foo'的值,同时为'b'解析器传参
>>> parser.parse_args(['--foo', 'b', '--baz', 'Z'])
Namespace(baz='Z', foo=True)

注意,parse_args()返回的对象只包含由命令行选择的主解析器和子解析器的属性(而不包含任何其他子解析器)。所以在上面的例子中,当a命令被指定时,只有foo和bar属性存在,当b命令被指定时,只有foo和baz属性存在。

类似地,当从子解析器请求帮助消息时,只会打印该特定解析器的help。help消息将不包括父解析器或兄弟解析器消息。(但是,可以通过如上所述向add_parser()提供help=参数来为每个子解析器命令提供帮助消息。)

#查看父解析器的help信息,会包括子解析器的信息
>>> parser.parse_args(['--help'])
usage: PROG [-h] [--foo] {a,b} ...

positional arguments:
  {a,b}       sub-command help
    a         a help
    b         b help

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

#查看a解析器的信息
>>> parser.parse_args(['a', '--help'])
usage: PROG a [-h] bar

positional arguments:
  bar         bar help

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

#查看b解析器的信息
>>> parser.parse_args(['b', '--help'])
usage: PROG b [-h] [--baz {X,Y,Z}]

optional arguments:
  -h, --help     show this help message and exit
  --baz {X,Y,Z}  baz help

add_subparsers()方法还支持title和description关键字参数。当其中之一出现时,子解析器的命令将出现在help输出中的它们自己的组中。例如:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> subparsers = parser.add_subparsers(title='subcommands',description='valid subcommands',help='additional help')
>>> subparsers.add_parser('foo')
ArgumentParser(prog=' foo', usage=None, description=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True)
>>> subparsers.add_parser('bar')
ArgumentParser(prog=' bar', usage=None, description=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True)
>>> parser.parse_args(['-h'])
usage: [-h] {foo,bar} ...

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

subcommands: #title的值
  valid subcommands #description的值

  {foo,bar}   additional help #help的值

此外,add_parser支持一个附加的aliases参数,该参数允许多个字符串引用同一个子解析器。这个例子,像svn一样,别名co作为checkout的缩写:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> subparsers = parser.add_subparsers()
>>> checkout = subparsers.add_parser('checkout', aliases=['co'])
>>> checkout.add_argument('foo')
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['co', 'bar'])
Namespace(foo='bar')

处理子命令的一种特别有效的方法是将add_subparsers()方法的使用与对set_defaults()的调用结合起来,这样每个子解析器都知道应该执行哪个Python函数。例如:

>>> def foo(args):
...     print(args.x * args.y)
... 
>>> def bar(args):
...     print('((%s))' % args.z)
... 
>>> parser = argparse.ArgumentParser()
>>> subparsers = parser.add_subparsers()

#设置子解析器'foo'
>>> parser_foo = subparsers.add_parser('foo')
>>> parser_foo.add_argument('-x', type=int, default=1)
_StoreAction(option_strings=['-x'], dest='x', nargs=None, const=None, default=1, type=<class 'int'>, choices=None, help=None, metavar=None)
>>> parser_foo.add_argument('y', type=float)
_StoreAction(option_strings=[], dest='y', nargs=None, const=None, default=None, type=<class 'float'>, choices=None, help=None, metavar=None)
>>> parser_foo.set_defaults(func=foo) #设置默认使用的func为foo函数

#设置子解析器'bar'
>>> parser_bar = subparsers.add_parser('bar')
>>> parser_bar.add_argument('z')
_StoreAction(option_strings=[], dest='z', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser_bar.set_defaults(func=bar)#设置默认使用的func为bar函数
>>> 
>>> args = parser.parse_args('foo 1 -x 2'.split())
>>> args
Namespace(func=<function foo at 0x10bfd5730>, x=2, y=1.0)
>>> args.func(args) #调用的是foo函数
2.0
>>> 
>>> args = parser.parse_args('bar XYZYX'.split())
>>> args
Namespace(func=<function bar at 0x10bfd5840>, z='XYZYX')
>>> args.func(args) #调用的是bar函数
((XYZYX))

通过这种方式,您可以让parse_args()在参数解析完成后调用适当的函数。将函数与这样的操作关联通常是处理每个子解析器的不同操作的最简单方法

但是,如果需要检查调用的子解析器的名称,那么add_subparsers()调用的dest关键字参数将起作用:

>>> parser = argparse.ArgumentParser()
#定义的是namespace中的参数名称
>>> subparsers = parser.add_subparsers(dest='subparser_name')

>>> subparser1 = subparsers.add_parser('1')
>>> subparser1.add_argument('-x')
_StoreAction(option_strings=['-x'], dest='x', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

>>> subparser2 = subparsers.add_parser('2')
>>> subparser2.add_argument('y')
_StoreAction(option_strings=[], dest='y', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

>>> parser.parse_args(['2', 'frobble'])
Namespace(subparser_name='2', y='frobble') #反映在这里

2)FileType对象

class argparse.FileType

argparse.FileType(mode='r', bufsize=-1, encoding=None, errors=None)

FileType工厂创建可以传递给ArgumentParser.add_argument()的type参数的对象。将FileType对象作为其type的参数将以文件的形式打开命令行参数,这些文件具有所请求的mode模式、缓冲区大小、编码和错误处理(有关详细信息,请参阅open()函数):

>>> parser = argparse.ArgumentParser()

>>> parser.add_argument('--raw', type=argparse.FileType('wb', 0))
_StoreAction(option_strings=['--raw'], dest='raw', nargs=None, const=None, default=None, type=FileType('wb', 0), choices=None, help=None, metavar=None)

>>> parser.add_argument('out', type=argparse.FileType('w', encoding='UTF-8'))
_StoreAction(option_strings=[], dest='out', nargs=None, const=None, default=None, type=FileType('w', encoding='UTF-8'), choices=None, help=None, metavar=None)

>>> 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' closefd=True>)

FileType对象理解伪参数'-',并自动将其转换为sys.stdin用于可读的FileType对象和sys.stdout给可写的FileType对象:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('infile', type=argparse.FileType('r'))
_StoreAction(option_strings=[], dest='infile', nargs=None, const=None, default=None, type=FileType('r'), choices=None, help=None, metavar=None)

>>> parser.parse_args(['-'])
Namespace(infile=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>) #说明将标准输入作为infile的值,因为这里设置FileType('r')为'r',可读

New in version 3.4: The encodings and errors keyword arguments.

3)参数组

ArgumentParser.add_argument_group(title=None, description=None)

默认情况下,ArgumentParser在显示help消息时将命令行参数分组为“位置positional参数”和“可选optional参数”。当参数的概念分组比默认的更好时,可以使用add_argument_group()方法创建适当的组:

>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)
#创建了一个组
>>> group = parser.add_argument_group('group')

#添加参数到组中
>>> group.add_argument('--foo', help='foo help')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help='foo help', metavar=None)
>>> 
>>> group.add_argument('bar', help='bar help')
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help='bar help', metavar=None)

>>> parser.print_help()
usage: PROG [--foo FOO] bar

group:
  --foo FOO  foo help
  bar        bar help

add_argument_group()方法返回一个参数组对象,该对象具有一个add_argument()方法,就像一个常规的ArgumentParser一样。

当一个参数被添加到组中时,解析器就像对待一个普通的参数一样对待它,但是会在一个单独的组中显示该参数以获取help消息。add_argument_group()方法接受title和description参数,这些参数可用于自定义这个显示:

>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)

#设置title = 'group1', description='group1 description'
>>> group1 = parser.add_argument_group('group1', 'group1 description')
>>> group1.add_argument('foo', help='foo help')
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help='foo help', metavar=None)

#设置title = 'group2', description='group2 description'
>>> group2 = parser.add_argument_group('group2', 'group2 description')
>>> group2.add_argument('--bar', help='bar help')
_StoreAction(option_strings=['--bar'], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help='bar help', metavar=None)
>>> 
>>> parser.print_help()
usage: PROG [--bar BAR] foo

group1:
  group1 description

  foo        foo help

group2:
  group2 description

  --bar BAR  bar help

注意,任何不在用户定义的组中的参数都将回到通常的“位置参数”和“可选参数”部分。

4)互斥

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')
_StoreTrueAction(option_strings=['--foo'], dest='foo', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> group.add_argument('--bar', action='store_false')
_StoreFalseAction(option_strings=['--bar'], dest='bar', nargs=0, const=False, default=True, type=None, choices=None, help=None, metavar=None)

#只有一个就能运行
>>> 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参数,以表明至少需要一个互斥参数:

>>> import argparse
>>> parser = argparse.ArgumentParser(prog='PROG')

>>> group = parser.add_mutually_exclusive_group(required=True)

>>> group.add_argument('--foo', action='store_true')
_StoreTrueAction(option_strings=['--foo'], dest='foo', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)

>>> group.add_argument('--bar', action='store_false')
_StoreFalseAction(option_strings=['--bar'], dest='bar', nargs=0, const=False, default=True, type=None, choices=None, help=None, metavar=None)

>>> parser.parse_args([]) #如果一个参数都没有就报错
usage: PROG [-h] (--foo | --bar)
PROG: error: one of the arguments --foo --bar is required

注意,当前互斥的参数组不支持add_argument_group()中的的title和description参数。

5)解析器默认值

ArgumentParser.set_defaults(**kwargs)

大多数时候,parse_args()返回的对象的属性将通过检查命令行参数和参数操作完全确定。

set_defaults()允许添加一些额外的属性,这些属性是在不检查命令行的情况下确定的:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('foo', type=int)
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)
>>> parser.set_defaults(bar=42, baz='badger')
>>> parser.parse_args(['736']) #命令行没给出,但是就有了bar和baz的值
Namespace(bar=42, baz='badger', foo=736)

注意,解析器级别的默认值总是覆盖参数级别的默认值:

>>> parser = argparse.ArgumentParser()

>>> parser.add_argument('--foo', default='bar') #参数级别的默认值
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='bar', type=None, choices=None, help=None, metavar=None)

>>> parser.set_defaults(foo='spam') #解析器级别的默认值
>>> parser.parse_args([])
Namespace(foo='spam')

在使用多个解析器时,解析器级别的缺省值尤其有用。有关此类型的示例,请参见上面的add_subparsers()方法。

得到默认值:

ArgumentParser.get_default(dest)

获取namespace属性的默认值,即由add_argument()或set_defaults()设置的默认值:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default='badger')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='badger', type=None, choices=None, help=None, metavar=None)
>>> parser.get_default('foo')
'badger'
>>> parser.set_defaults(bar='baz')
>>> parser.get_default('bar')
'baz'

6)打印帮助信息

在大多数典型的应用程序中,parse_args()将负责格式化和打印任何使用或错误消息。然而,有几种格式化方法:

ArgumentParser.print_usage(file=None)

打印一个关于应该如何在命令行上调用ArgumentParser的简短描述。如果文件为空,则使用sys.stdout。

ArgumentParser.print_help(file=None)

打印一条help消息,包括程序使用情况和关于ArgumentParser注册的参数的信息。如果文件为空,则使用sys.stdout。

这些方法也有一些变体,它们只是返回一个字符串,而不是打印它:

ArgumentParser.format_usage()

返回一个字符串,该字符串包含应该如何在命令行上调用ArgumentParser的简短描述。

ArgumentParser.format_help()

返回一个包含帮助消息的字符串,包括程序使用情况和关于ArgumentParser注册的参数的信息。

举例:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default='badger')
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='badger', type=None, choices=None, help=None, metavar=None)
>>> parser.get_default('foo')
'badger'
>>> parser.set_defaults(bar='baz')
>>> parser.get_default('bar')
'baz'

>>> parser.print_usage()
usage: [-h] [--foo FOO]

>>> parser.print_help()
usage: [-h] [--foo FOO]

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

>>> parser.format_usage()
'usage: [-h] [--foo FOO]
'

>>> parser.format_help()
'usage: [-h] [--foo FOO]

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

7)部分解析

ArgumentParser.parse_known_args(args=None, namespace=None)

有时一个脚本可能只解析几个命令行参数,将剩余的参数传递给另一个脚本或程序

在这些情况下,parse_known_args()方法可能很有用。它的工作原理很像parse_args(),只是在出现额外参数时不会产生错误。相反,它返回一个包含填充namespace和剩余参数字符串列表的两项元组。

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_true')
_StoreTrueAction(option_strings=['--foo'], dest='foo', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('bar')
_StoreAction(option_strings=[], dest='bar', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_known_args(['--foo', '--badger', 'BAR', 'spam'])
(Namespace(bar='BAR', foo=True), ['--badger', 'spam'])

⚠️警告:前缀匹配规则适用于parse_known_args()。解析器可能会使用一个选项,即使它只是它的一个已知选项的前缀,而不是将它留在剩余的arguments列表中。

8)定制文件解析

ArgumentParser.convert_arg_line_to_args(arg_line)

从文件中读取的参数(请参阅fromfile_prefix_chars关键字参数到ArgumentParser构造函数)是从每一行读取一个参数。convert_arg_line_to_args()可以被覆盖,以便更好地阅读。

这个方法接受一个参数arg_line,它是从参数文件中读取的字符串。它返回从该字符串解析的参数列表。这个方法按顺序在从参数文件中读取的每行调用一次。

此方法的一个有用覆盖是将每个空格分隔的单词作为一个参数。下面的例子演示了如何做到这一点:

class MyArgumentParser(argparse.ArgumentParser):
    def convert_arg_line_to_args(self, arg_line):
        return arg_line.split()

9)Exiting methods存在方法

ArgumentParser.exit(status=0, message=None)

此方法终止程序,以指定的状态退出,如果给定,则在此之前打印一条消息。

ArgumentParser.error(message)

此方法将一个usage消息(包括发送给标准错误的消息)打印出来,并使用状态代码2终止程序。

原文地址:https://www.cnblogs.com/wanghui-garcia/p/10658000.html