python 标准库 argparse 命令行选项

每日一词:
eternity n 永恒 不朽
近义词:
invariability n 恒久不变的东西
perpetuity n 永久 永恒
timelessness n 永恒
permanence n 永久 持久
everlasting adj永恒的
源码
源代码: Lib/argparse.py
argparse 模块可以让人轻松编写用户友好的命令行接口。程序定义它需要的参数,然后 argparse 将弄清如何从 sys.argv 解析出那些参数。 argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。
示例
以下代码是一个 Python 程序,它获取一个整数列表并计算总和或者最大值:
1 | import argparse |
假设上面的 Python 代码保存在名为 prog.py 的文件中,它可以在命令行运行并提供有用的帮助消息:
1 | $ python prog.py -h |
当使用适当的参数运行时,它会输出命令行传入整数的总和或者最大值:
1 | $ python prog.py 1 2 3 4 |
如果传入无效参数,则会报出错误:
1 | $ python prog.py a b c |
以下部分将引导你完成这个示例。
创建一个解析器
使用 argparse 的第一步是创建一个 ArgumentParser 对象:
1 | parser = argparse.ArgumentParser(description='Process some integers.') |
ArgumentParser 对象包含将命令行解析成 Python 数据类型所需的全部信息。
添加参数
给一个 ArgumentParser 添加程序参数信息是通过调用 add_argument() 方法完成的。通常,这些调用指定 ArgumentParser 如何获取命令行字符串并将其转换为对象。这些信息在 parse_args() 调用时被存储和使用。例如:
1 | parser.add_argument('integers', metavar='N', type=int, nargs='+', |
稍后,调用 parse_args() 将返回一个具有 integers 和 accumulate 两个属性的对象。integers 属性将是一个包含一个或多个整数的列表,而 accumulate 属性当命令行中指定了 --sum 参数时将是 sum() 函数,否则则是 max() 函数。
解析参数
ArgumentParser 通过 parse_args() 方法解析参数。它将检查命令行,把每个参数转换为适当的类型然后调用相应的操作。在大多数情况下,这意味着一个简单的 Namespace 对象将从命令行参数中解析出的属性构建:
1 | parser.parse_args(['--sum', '7', '-1', '42']) |
在脚本中,通常 parse_args() 会被不带参数调用,而 ArgumentParser 将自动从 sys.argv 中确定命令行参数。
ArgumentParser 对象
创建一个新的 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)
以下部分描述这些参数如何使用。
prog
默认情况下,ArgumentParser 对象使用 sys.argv[0] 来确定如何在帮助消息中显示程序名称。这一默认值几乎总是可取的,因为它将使帮助消息与从命令行调用此程序的方式相匹配。例如,对于有如下代码的名为 myprogram.py 的文件:
1 | import argparse |
该程序的帮助信息将显示 myprogram.py 作为程序名称(无论程序从何处被调用):
1 | $ python myprogram.py --help |
要更改这样的默认行为,可以使用 prog= 参数为 ArgumentParser 提供另一个值:
1 | parser = argparse.ArgumentParser(prog='myprogram') |
需要注意的是,无论是从 sys.argv[0] 或是从 prog= 参数确定的程序名称,都可以在帮助消息里通过 %(prog)s 格式串来引用。
1 | parser = argparse.ArgumentParser(prog='myprogram') |
usage
默认情况下,ArgumentParser 根据它包含的参数来构建用法消息:
1 | parser = argparse.ArgumentParser(prog='PROG') |
可以通过 usage= 关键字参数覆盖这一默认消息:
1 | parser = argparse.ArgumentParser(prog='PROG', usage='%(prog)s [options]') |
在用法消息中可以使用 %(prog)s 格式说明符来填入程序名称。
description
大多数对 ArgumentParser 构造方法的调用都会使用 description= 关键字参数。这个参数简要描述这个程度做什么以及怎么做。在帮助消息中,这个描述会显示在命令行用法字符串和各种参数的帮助消息之间:
1 | parser = argparse.ArgumentParser(description='A foo that bars') |
在默认情况下,description 将被换行以便适应给定的空间。如果想改变这种行为,见 formatter_class 参数。
epilog
一些程序喜欢在 description 参数后显示额外的对程序的描述。这种文字能够通过给 ArgumentParser:: 提供 epilog= 参数而被指定。
1 | parser = argparse.ArgumentParser( |
和 description 参数一样,epilog= text 在默认情况下会换行,但是这种行为能够被调整通过提供 formatter_class 参数给 ArgumentParse.
parents
有些时候,少数解析器会使用同一系列参数。 单个解析器能够通过提供 parents= 参数给 ArgumentParser 而使用相同的参数而不是重复这些参数的定义。parents= 参数使用 ArgumentParser 对象的列表,从它们那里收集所有的位置和可选的行为,然后将这写行为加到正在构建的 ArgumentParser 对象。
1 | parent_parser = argparse.ArgumentParser(add_help=False) |
请注意大多数父解析器会指定 add_help=False . 否则, ArgumentParse 将会看到两个 -h/--help 选项(一个在父参数中一个在子参数中)并且产生一个错误。
你在传parents=给那些解析器时必须完全初始化它们。如果你在子解析器之后改变父解析器是,这些改变不会反映在子解析器上。
formatter_class
ArgumentParser 对象允许通过指定备用格式化类来自定义帮助格式。目前,有四种这样的类。
- class
argparse.RawDescriptionHelpFormatter - class
argparse.RawTextHelpFormatter - class
argparse.ArgumentDefaultsHelpFormatter class
argparse.MetavarTypeHelpFormatterRawDescriptionHelpFormatter和RawTextHelpFormatter在正文的描述和展示上给与了更多的控制。ArgumentParser对象会将 description 和 epilog 的文字在命令行中自动换行。
1 | parser = argparse.ArgumentParser( |
传 RawDescriptionHelpFormatter 给 formatter_class= 表示 description 和 epilog 已经被正确的格式化了,不能在命令行中被自动换行:
1 | parser = argparse.ArgumentParser( |
RawTextHelpFormatter 保留所有种类文字的空格,包括参数的描述。然而,多重的新行会被替换成一行。如果你想保留多重的空白行,可以在新行之间加空格。
ArgumentDefaultsHelpFormatter 自动添加默认的值的信息到每一个帮助信息的参数中:
1 | parser = argparse.ArgumentParser( |
MetavarTypeHelpFormatter 为它的值在每一个参数中使用 type 的参数名当作它的显示名(而不是使用通常的格式 dest ):
1 | parser = argparse.ArgumentParser( |
prefix_chars
许多命令行会使用 - 当作前缀,比如 -f/--foo。如果解析器需要支持不同的或者额外的字符,比如像 +f 或者 /foo 的选项,可以在参数解析构建器中使用 prefix_chars= 参数。
1 | parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+') |
The prefix_chars= 参数默认使用 '-'. 支持一系列字符,但是不包括 - ,这样会产生不被允许的 -f/--foo 选项。
fromfile_prefix_chars
有些时候,先举个例子,当处理一个特别长的参数列表的时候,把它存入一个文件中而不是在命令行打出来会很有意义。如果 fromfile_prefix_chars= 参数提供给 ArgumentParser 构造函数,之后所有类型的字符的参数都会被当成文件处理,并且会被文件包含的参数替代。举个栗子:
1 | with open('args.txt', 'w') as fp: |
从文件读取的参数在默认情况下必须一个一行(但是可参见 convert_arg_line_to_args())并且它们被视为与命令行上的原始文件引用参数位于同一位置。所以在以上例子中,['-f', 'foo', '@args.txt'] 的表示和 ['-f', 'foo', '-f', 'bar'] 的表示相同。
fromfile_prefix_chars= 参数默认为 None,意味着参数不会被当作文件对待。
argument_default
一般情况下,参数默认会通过设置一个默认到 add_argument() 或者调用带一组指定键值对的 ArgumentParser.set_defaults() 方法。但是有些时候,为参数指定一个普遍适用的解析器会更有用。这能够通过传输 argument_default= 关键词参数给 ArgumentParser 来完成。举个栗子,要全局禁止在 parse_args() 中创建属性,我们提供 argument_default=SUPPRESS:
1 | parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS) |
allow_abbrev
正常情况下,当你向 ArgumentParser 的 parse_args() 方法传入一个参数列表时,它会 recognizes abbreviations。
这个特性可以设置 allow_abbrev 为 False 来关闭:
1 | parser = argparse.ArgumentParser(prog='PROG', allow_abbrev=False) |
conflict_handler
ArgumentParser 对象不允许在相同选项字符串下有两种行为。默认情况下, ArgumentParser 对象会产生一个异常如果去创建一个正在使用的选项字符串参数。
1 | parser = argparse.ArgumentParser(prog='PROG') |
有些时候(例如:使用 parents),重写旧的有相同选项字符串的参数会更有用。为了产生这种行为, 'resolve' 值可以提供给 ArgumentParser 的 conflict_handler= 参数:
1 | parser = argparse.ArgumentParser(prog='PROG', conflict_handler='resolve') |
注意 ArgumentParser 对象只能移除一个行为如果它所有的选项字符串都被重写。所以,在上面的例子中,旧的 -f/--foo 行为 回合 -f 行为保持一样, 因为只有 --foo 选项字符串被重写。
add_help
默认情况下,ArgumentParser 对象添加一个简单的显示解析器帮助信息的选项。举个栗子,考虑一个名为 myprogram.py 的文件包含如下代码:
1 | import argparse |
如果 -h or --help 在命令行中被提供, 参数解析器帮助信息会打印:
1 | $ python myprogram.py --help |
有时候可能会需要关闭额外的帮助信息。这可以通过在 ArgumentParser 中设置 add_help= 参数为 False 来实现。
1 | parser = argparse.ArgumentParser(prog='PROG', add_help=False) |
帮助选项一般为 -h/--help。如果 prefix_chars= 被指定并且没有包含 - 字符,在这种情况下, -h --help 不是有效的选项。此时, prefix_chars 的第一个字符将用作帮助选项的前缀。
1 | parser = argparse.ArgumentParser(prog='PROG', prefix_chars='+/') |
add_argument() 方法
ArgumentParser.add_argument(name or flags…[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])
定义单个的命令行参数应当如何解析。每个形参都在下面有它自己更多的描述,长话短说有:
- name or flags - 一个命名或者一个选项字符串的列表,例如
foo或-f, --foo。 - action - 当参数在命令行中出现时使用的动作基本类型。
- nargs - 命令行参数应当消耗的数目。
- const - 被一些 action 和 nargs 选择所需求的常数。
- default - 当参数未在命令行中出现时使用的值。
- type - 命令行参数应当被转换成的类型。
- choices - 可用的参数的容器。
- required - 此命令行选项是否可省略 (仅选项可用)。
- help - 一个此选项作用的简单描述。
- metavar - 在使用方法消息中使用的参数值示例。
dest - 被添加到
parse_args()所返回对象上的属性名。以下部分描述这些参数如何使用。
name or flags
add_argument() 方法必须知道它是否是一个选项,例如 -f 或 --foo,或是一个位置参数,例如一组文件名。第一个传递给 add_argument() 的参数必须是一系列 flags 或者是一个简单的参数名。例如,可以选项可以被这样创建:
1 | parser.add_argument('-f', '--foo') |
而位置参数可以这么创建:
1 | parser.add_argument('bar') |
当 parse_args() 被调用,选项会以 - 前缀识别,剩下的参数则会被假定为位置参数:
1 | parser = argparse.ArgumentParser(prog='PROG') |
action
ArgumentParser 对象将命令行参数与动作相关联。这些动作可以做与它们相关联的命令行参数的任何事,尽管大多数动作只是简单的向 parse_args() 返回的对象上添加属性。action 命名参数指定了这个命令行参数应当如何处理。供应的动作有:
'store'- 存储参数的值。这是默认的动作。例如:1
2
3
4parser = argparse.ArgumentParser()
parser.add_argument('--foo')
parser.parse_args('--foo 1'.split())
Namespace(foo='1')'store_const'- 存储被 const 命名参数指定的值。'store_const'动作通常用在选项中来指定一些标志。例如:1
2
3
4parser = argparse.ArgumentParser()
parser.add_argument('--foo', action='store_const', const=42)
parser.parse_args(['--foo'])
Namespace(foo=42)'store_true'and'store_false'- 这些是'store_const'分别用作存储True和False值的特殊用例。另外,它们的默认值分别为False和True。例如:1
2
3
4
5
6parser = argparse.ArgumentParser()
parser.add_argument('--foo', action='store_true')
parser.add_argument('--bar', action='store_false')
parser.add_argument('--baz', action='store_false')
parser.parse_args('--foo --bar'.split())
Namespace(foo=True, bar=False, baz=True)'append'- 存储一个列表,并且将每个参数值追加到列表中。在允许多次使用选项时很有用。例如:1
2
3
4parser = argparse.ArgumentParser()
parser.add_argument('--foo', action='append')
parser.parse_args('--foo 1 --foo 2'.split())
Namespace(foo=['1', '2'])'append_const'- 这存储一个列表,并将 const 命名参数指定的值追加到列表中。(注意 const 命名参数默认为None。)’append_const’ 动作一般在多个参数需要在同一列表中存储常数时会有用。例如:1
2
3
4
5parser = argparse.ArgumentParser()
parser.add_argument('--str', dest='types', action='append_const', const=str)
parser.add_argument('--int', dest='types', action='append_const', const=int)
parser.parse_args('--str --int'.split())
Namespace(types=[<class 'str'>, <class 'int'>])'count'- 计算一个关键字参数出现的数目或次数。例如,对于一个增长的详情等级来说有用:1
2
3
4parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='count', default=0)
parser.parse_args(['-vvv'])
Namespace(verbose=3)Note, the default will be
Noneunless explicitly set to 0.'help'- 打印所有当前解析器中的选项和参数的完整帮助信息,然后退出。默认情况下,一个 help 动作会被自动加入解析器。关于输出是如何创建的,参与ArgumentParser。'version'- 期望有一个version=命名参数在add_argument()调用中,并打印版本信息并在调用后退出:1
2
3
4
5import argparse
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('--version', action='version', version='%(prog)s 2.0')
parser.parse_args(['--version'])
PROG 2.0'extend'- This stores a list, and extends each argument value to the list. Example usage:1
2
3
4parser = argparse.ArgumentParser()
parser.add_argument("--foo", action="extend", nargs="+", type=str)
parser.parse_args(["--foo", "f1", "--foo", "f2", "f3", "f4"])
Namespace(foo=['f1', 'f2', 'f3', 'f4'])
3.8 新版功能.
您还可以通过传递 Action 子类或实现相同接口的其他对象来指定任意操作。建议的方法是扩展 Action,覆盖 __call__ 方法和可选的 __init__ 方法。
一个自定义动作的例子:
1 | class FooAction(argparse.Action): |
nargs
ArgumentParser 对象通常关联一个单独的命令行参数到一个单独的被执行的动作。 nargs 命名参数关联不同数目的命令行参数到单一动作。支持的值有:
N(一个整数)。命令行中的N个参数会被聚集到一个列表中。 例如:>>>
1
2
3
4
5>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs=2)
>>> parser.add_argument('bar', nargs=1)
>>> parser.parse_args('c --foo a b'.split())
Namespace(bar=['c'], foo=['a', 'b'])注意
nargs=1会产生一个单元素列表。这和默认的元素本身是不同的。'?'。如果可能的话,会从命令行中消耗一个参数,并产生一个单一项。如果当前没有命令行参数,则会产生 default 值。注意,对于选项,有另外的用例 - 选项字符串出现但没有跟随命令行参数,则会产生 const 值。一些说用用例:1
2
3
4
5
6
7
8
9parser = argparse.ArgumentParser()
parser.add_argument('--foo', nargs='?', const='c', default='d')
parser.add_argument('bar', nargs='?', default='d')
parser.parse_args(['XX', '--foo', 'YY'])
Namespace(bar='XX', foo='YY')
parser.parse_args(['XX', '--foo'])
Namespace(bar='XX', foo='c')
parser.parse_args([])
Namespace(bar='d', foo='d')nargs='?'的一个更普遍用法是允许可选的输入或输出文件:1
2
3
4
5
6
7
8
9
10
11parser = argparse.ArgumentParser()
parser.add_argument('infile', nargs='?', type=argparse.FileType('r'),
default=sys.stdin)
parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'),
default=sys.stdout)
parser.parse_args(['input.txt', 'output.txt'])
Namespace(infile=<_io.TextIOWrapper name='input.txt' encoding='UTF-8'>,
outfile=<_io.TextIOWrapper name='output.txt' encoding='UTF-8'>)
parser.parse_args([])
Namespace(infile=<_io.TextIOWrapper name='<stdin>' encoding='UTF-8'>,
outfile=<_io.TextIOWrapper name='<stdout>' encoding='UTF-8'>)'*'。所有当前命令行参数被聚集到一个列表中。注意通过nargs='*'来实现多个位置参数通常没有意义,但是多个选项是可能的。例如:1
2
3
4
5
6parser = argparse.ArgumentParser()
parser.add_argument('--foo', nargs='*')
parser.add_argument('--bar', nargs='*')
parser.add_argument('baz', nargs='*')
parser.parse_args('a b --foo x y --bar 1 2'.split())
Namespace(bar=['1', '2'], baz=['a', 'b'], foo=['x', 'y'])'+'。和'*'类似,所有当前命令行参数被聚集到一个列表中。另外,当前没有至少一个命令行参数时会产生一个错误信息。例如:1
2
3
4
5
6
7parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('foo', nargs='+')
parser.parse_args(['a', 'b'])
Namespace(foo=['a', 'b'])
parser.parse_args([])
usage: PROG [-h] foo [foo ...]
PROG: error: the following arguments are required: fooargarse.REMAINDER。所有剩余的命令行参数被聚集到一个列表中。这通常在从一个命令行功能传递参数到另一个命令行功能中时有用:>>>
1
2
3
4
5
6parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('--foo')
parser.add_argument('command')
parser.add_argument('args', nargs=argparse.REMAINDER)
print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')
如果不提供 nargs 命名参数,则消耗参数的数目将被 action 决定。通常这意味着单一项目(非列表)消耗单一命令行参数。
const
add_argument() 的const 参数用于保存不从命令行中读取但被各种 ArgumentParser 动作需求的常数值。最常用的两例为:
- 当
add_argument()通过action='store_const'或action='append_const调用时。这些动作将const值添加到parse_args()返回的对象的属性中。在 action 的描述中查看案例。 - 当
add_argument()通过选项(例如-f或--foo)调用并且nargs='?'时。这会创建一个可以跟随零个或一个命令行参数的选项。当解析命令行时,如果选项后没有参数,则将用const代替。在 nargs 描述中查看案例。
对 'store_const' 和 'append_const' 动作, const 命名参数必须给出。对其他动作,默认为 None。
default
所有选项和一些位置参数可能在命令行中被忽略。add_argument() 的命名参数 default,默认值为 None,指定了在命令行参数未出现时应当使用的值。对于选项, default 值在选项未在命令行中出现时使用:
1 | parser = argparse.ArgumentParser() |
如果 default 值是一个字符串,解析器解析此值就像一个命令行参数。特别是,在将属性设置在 Namespace 的返回值之前,解析器应用任何提供的 type 转换参数。否则解析器使用原值:
1 | parser = argparse.ArgumentParser() |
对于 nargs 等于 ? 或 * 的位置参数, default 值在没有命令行参数出现时使用。
1 | parser = argparse.ArgumentParser() |
提供 default=argparse.SUPPRESS 导致命令行参数未出现时没有属性被添加:
1 | parser = argparse.ArgumentParser() |
type
默认情况下,ArgumentParser 对象将命令行参数当作简单字符串读入。然而,命令行字符串经常需要被当作其它的类型,比如 float 或者 int。add_argument() 的 type 关键词参数允许任何的类型检查和类型转换。一般的内建类型和函数可以直接被 type 参数使用。
1 | parser = argparse.ArgumentParser() |
当 type 参数被应用到默认参数时,请参考 default 参数的部分。
type 也可以指定写入文件,通过指定 mode=, bufsize=, encoding= and errors= 等参数调用open方法打开文件。举个栗子,设定FileType('w') 参数可以设定创建一个可写的文件。
1 | parser = argparse.ArgumentParser() |
type= can take any callable that takes a single string argument and returns the converted value:
1 | def perfect_square(string): |
choices 关键词参数可能会使类型检查者更方便的检查一个范围的值。
1 | parser = argparse.ArgumentParser(prog='PROG') |
choices
一些命令行参数从一组受限制的值中获取。这些可以通过容器对象,借助choice关键字参数传递给 add_argument() 来处理,分析命令行时,将检查参数值,如果参数不是可接受的值之一,将显示错误消息:
1 | >>> parser = argparse.ArgumentParser(prog='game.py') |
需要注意的是 类型转换执行后执行检查, choice容器必须匹配这些类型声明。
1 | parser = argparse.ArgumentParser(prog='doors.py') |
任何容器可以通过 choice值来传递参数,例如 list 和 set 对象,亦或者是支持的自定义容器。
required
通常情况下,可以通过 -f and --bar参数声明可选参数,这些参数可以在命令行执行的时候被忽略。如果想把这些单数设置成必须参数,则需要在add_argument()参数中将 require参数设置成True
1 | >>> parser = argparse.ArgumentParser() |
就像上述例子显示的情况一样。如果一个功能被标识为必须的,在命令行执行的时候,会不断报错。
必须参数被认为不是一个好习惯。用户期望功能都是可选的,避免成为必须参数