本文最后更新于:2024年12月27日 下午

我们经常需要在 Python 程序运行过程中获取命令行参数,argparse 模块是 Python 标准库中推荐的命令行解析模块,本文介绍相关用法。

sys.argv

Python内置的sys.argv保存了完整的参数列表,我们可以从中解析出需要的参数:

1
2
3
# args.py
import sys
print(sys.argv)

执行如下命令执行 python 脚本

1
python args.py test1 test2 test3

输出:

1
['args.py', 'test1', 'test2', 'test3']

这种方式能应付简单的参数,但参数稍微复杂点,比如可以使用-d复制目录,使用--filename *.py过滤文件名等,解析起来就非常麻烦。

为了简化参数解析,我们可以使用内置的argparse库,定义好各个参数类型后,它能直接返回有效的参数。

argparse

argparse 模块可以让人轻松编写用户友好的命令行接口。程序定义它需要的参数,然后 argparse 将弄清如何从 sys.argv 解析出那些参数。 argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。

创建解析器 ArgumentParser

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

1
2
import argparse
parser = argparse.ArgumentParser(description='Process some integers.')

ArgumentParser 对象包含将命令行解析成 Python 数据类型所需的全部信息。

1
class argparse.ArgumentParser(prog=None, usage=None, description=None, epilog=None, parents=[], formatter_class=argparse.HelpFormatter, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True, allow_abbrev=True, exit_on_error=True)

创建一个新的 ArgumentParser 对象。所有的参数都应当作为关键字参数传入:

文档链接:https://docs.python.org/zh-cn/3.10/library/argparse.html#argparse.ArgumentParser

参数名称 描述
prog 程序的名称 (默认值: os.path.basename(sys.argv[0]))
usage 描述程序用途的字符串(默认值:从添加到解析器的参数生成)
description 要在参数帮助信息之前显示的文本(默认:无文本)
epilog 要在参数帮助信息之后显示的文本(默认:无文本)
parents 一个 ArgumentParser 对象的列表,它们的参数也应包含在内
formatter_class 用于自定义帮助文档输出格式的类
prefix_chars 可选参数的前缀字符集合(默认值: ‘-’)
fromfile_prefix_chars 当需要从文件中读取其他参数时,用于标识文件名的前缀字符集合(默认值: None
argument_default 参数的全局默认值(默认值: None
conflict_handler 解决冲突选项的策略(通常是不必要的)
add_help 为解析器添加一个 -h/--help 选项(默认值: True
allow_abbrev 如果缩写是无歧义的,则允许缩写长选项 (默认值:True
exit_on_error 决定当错误发生时是否让 ArgumentParser 附带错误信息退出。 (默认值: True)

在 3.5 版更改: 增加了 allow_abbrev 参数。

在 3.8 版更改: 在之前的版本中,allow_abbrev 还会禁用短旗标分组,例如 -vv 表示为 -v -v

在 3.9 版更改: 添加了 exit_on_error 形参。

prog

默认情况下,ArgumentParser 对象使用 sys.argv[0] 来确定如何在帮助消息中显示程序名称。这一默认值几乎总是可取的,因为它将使帮助消息与从命令行调用此程序的方式相匹配。

例如,对于有如下代码的名为 args.py 的文件:

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

调用 -h 参数:

1
2
3
4
5
6
python args.py -h
usage: args.py [-h] [--foo FOO]

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

输出信息中的 args.py 就是从 sys.argv[0] 中获取的。

如果需要修改这项内容,可以修改 prog 参数:

1
2
3
4
import argparse
parser = argparse.ArgumentParser(prog='myprogram')
parser.add_argument('--foo', help='foo help')
args = parser.parse_args()

调用 -h 参数:

1
2
3
4
5
6
python args.py -h
usage: myprogram [-h] [--foo FOO]

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

也可以用 parser.print_help() 来调用帮助信息:

1
2
3
4
import argparse
parser = argparse.ArgumentParser(prog='myprogram')
parser.add_argument('--foo', help='foo help')
parser.print_help()

输出信息:

1
2
3
4
5
usage: myprogram [-h] [--foo FOO]

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

无论是从 sys.argv[0] 或是从 prog= 参数确定的程序名称,都可以在帮助消息里通过 %(prog)s 格式说明符来引用。

1
2
3
4
import argparse
parser = argparse.ArgumentParser(prog='myprogram')
parser.add_argument('--foo', help='foo of the %(prog)s program')
parser.print_help()

输出信息:

1
2
3
4
5
usage: myprogram [-h] [--foo FOO]

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

usage

默认情况下,ArgumentParser 根据它包含的参数来构建用法消息:

1
2
3
4
5
6
7
8
9
10
11
12
>>> 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

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

可以通过 usage= 关键字参数覆盖这一默认消息:

1
2
3
4
5
6
7
8
9
10
11
12
>>> parser = argparse.ArgumentParser(prog='PROG', usage='%(prog)s [options]')
>>> parser.add_argument('--foo', nargs='?', help='foo help')
>>> parser.add_argument('bar', nargs='+', help='bar help')
>>> parser.print_help()
usage: PROG [options]

positional arguments:
bar bar help

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

在用法消息中可以使用 %(prog)s 格式说明符来填入程序名称。

description

大多数对 ArgumentParser 构造方法的调用都会使用 description= 关键字参数。 这个参数简要描述这个程序做什么以及怎么做。 在帮助消息中,这个描述会显示在命令行用法字符串和各种参数的帮助消息之间:

1
2
3
4
5
6
7
8
>>> parser = argparse.ArgumentParser(description='A foo that bars')
>>> parser.print_help()
usage: argparse.py [-h]

A foo that bars

options:
-h, --help show this help message and exit

在默认情况下,description 将被换行以便适应给定的空间。如果想改变这种行为,见 formatter_class 参数。

epilog

一些程序喜欢在 description 参数后显示额外的对程序的描述。这种文字能够通过给 ArgumentParser 提供 epilog= 参数而被指定。

1
2
3
4
5
6
7
8
9
10
11
12
>>> parser = argparse.ArgumentParser(
... description='A foo that bars',
... epilog="And that's how you'd foo a bar")
>>> parser.print_help()
usage: argparse.py [-h]

A foo that bars

options:
-h, --help show this help message and exit

And that's how you'd foo a bar

description 参数一样,epilog= text 在默认情况下会换行,但是这种行为能够被调整通过提供 formatter_class 参数给 ArgumentParse.

parents

有些时候,少数解析器会使用同一系列参数。 单个解析器能够通过提供 parents= 参数给 ArgumentParser 而使用相同的参数而不是重复这些参数的定义。parents= 参数使用 ArgumentParser 对象的列表,从它们那里收集所有的位置和可选的行为,然后将这写行为加到正在构建的 ArgumentParser 对象。

1
2
3
4
5
6
7
8
9
10
11
12
>>> parent_parser = argparse.ArgumentParser(add_help=False)
>>> parent_parser.add_argument('--parent', type=int)

>>> foo_parser = argparse.ArgumentParser(parents=[parent_parser])
>>> foo_parser.add_argument('foo')
>>> foo_parser.parse_args(['--parent', '2', 'XXX'])
Namespace(foo='XXX', parent=2)

>>> bar_parser = argparse.ArgumentParser(parents=[parent_parser])
>>> bar_parser.add_argument('--bar')
>>> bar_parser.parse_args(['--bar', 'YYY'])
Namespace(bar='YYY', parent=None)

请注意大多数父解析器会指定 add_help=False . 否则, ArgumentParse 将会看到两个 -h/--help 选项(一个在父参数中一个在子参数中)并且产生一个错误。

注解: 你在通过 parents= 传递解析器之前必须完全初始化它们。 如果你在子解析器之后改变父解析器,这些改变将不会反映在子解析器上。

formatter_class

ArgumentParser 对象允许通过指定备用格式化类来自定义帮助格式。目前,有四种这样的类。

  • class argparse.RawDescriptionHelpFormatter
  • class argparse.RawTextHelpFormatter
  • class argparse.ArgumentDefaultsHelpFormatter
  • class argparse.MetavarTypeHelpFormatter

RawDescriptionHelpFormatterRawTextHelpFormatter 在正文的描述和展示上给与了更多的控制。ArgumentParser 对象会将 descriptionepilog 的文字在命令行中自动换行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> parser = argparse.ArgumentParser(
... prog='PROG',
... description='''this description
... was indented weird
... but that is okay''',
... epilog='''
... likewise for this epilog whose whitespace will
... be cleaned up and whose words will be wrapped
... across a couple lines''')
>>> parser.print_help()
usage: PROG [-h]

this description was indented weird but that is okay

options:
-h, --help show this help message and exit

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

RawDescriptionHelpFormatterformatter_class= 表示 descriptionepilog 已经被正确的格式化了,不能在命令行中被自动换行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> parser = argparse.ArgumentParser(
... prog='PROG',
... formatter_class=argparse.RawDescriptionHelpFormatter,
... description=textwrap.dedent('''\
... Please do not mess up this text!
... --------------------------------
... I have indented it
... exactly the way
... I want it
... '''))
>>> parser.print_help()
usage: PROG [-h]

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

options:
-h, --help show this help message and exit

RawTextHelpFormatter 保留所有种类文字的空格,包括参数的描述。然而,多重的新行会被替换成一行。如果你想保留多重的空白行,可以在新行之间加空格。

ArgumentDefaultsHelpFormatter 自动添加默认的值的信息到每一个帮助信息的参数中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> parser = argparse.ArgumentParser(
... prog='PROG',
... formatter_class=argparse.ArgumentDefaultsHelpFormatter)
>>> parser.add_argument('--foo', type=int, default=42, help='FOO!')
>>> parser.add_argument('bar', nargs='*', default=[1, 2, 3], help='BAR!')
>>> parser.print_help()
usage: PROG [-h] [--foo FOO] [bar ...]

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

options:
-h, --help show this help message and exit
--foo FOO FOO! (default: 42)

MetavarTypeHelpFormatter 为它的值在每一个参数中使用 type 的参数名当作它的显示名(而不是使用通常的格式 dest ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> parser = argparse.ArgumentParser(
... prog='PROG',
... formatter_class=argparse.MetavarTypeHelpFormatter)
>>> parser.add_argument('--foo', type=int)
>>> parser.add_argument('bar', type=float)
>>> parser.print_help()
usage: PROG [-h] [--foo int] float

positional arguments:
float

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

prefix_chars

许多命令行会使用 - 当作前缀,比如 -f/--foo。如果解析器需要支持不同的或者额外的字符,比如像 +f 或者 /foo 的选项,可以在参数解析构建器中使用 prefix_chars= 参数。

1
2
3
4
5
>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+')
>>> parser.add_argument('+f')
>>> parser.add_argument('++bar')
>>> parser.parse_args('+f X ++bar Y'.split())
Namespace(bar='Y', f='X')

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

fromfile_prefix_chars

在某些时候,例如在处理一个特别长的参数列表的时候,把参数列表存入一个文件中而不是在命令行中打印出来会更有意义。 如果提供 fromfile_prefix_chars= 参数给 ArgumentParser 构造器,则任何以指定字符打头的参数都将被当作文件来处理,并将被它们包含的参数所替代。

举例来说:

1
2
3
4
5
6
>>> 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')

从文件读取的参数在默认情况下必须一个一行(但是可参见 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
2
3
4
5
6
7
>>> parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
>>> parser.add_argument('--foo')
>>> parser.add_argument('bar', nargs='?')
>>> parser.parse_args(['--foo', '1', 'BAR'])
Namespace(bar='BAR', foo='1')
>>> parser.parse_args([])
Namespace()

allow_abbrev

正常情况下,当你向 ArgumentParserparse_args() 方法传入一个参数列表时,它会 recognizes abbreviations。

这个特性可以设置 allow_abbrevFalse 来关闭:

1
2
3
4
5
6
>>> parser = argparse.ArgumentParser(prog='PROG', allow_abbrev=False)
>>> parser.add_argument('--foobar', action='store_true')
>>> parser.add_argument('--foonley', action='store_false')
>>> parser.parse_args(['--foon'])
usage: PROG [-h] [--foobar] [--foonley]
PROG: error: unrecognized arguments: --foon

3.5 新版功能.

conflict_handler

ArgumentParser 对象不允许在相同选项字符串下有两种行为。默认情况下, ArgumentParser 对象会产生一个异常如果去创建一个正在使用的选项字符串参数。

>>>

1
2
3
4
5
6
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-f', '--foo', help='old foo help')
>>> parser.add_argument('--foo', help='new foo help')
Traceback (most recent call last):
..
ArgumentError: argument --foo: conflicting option string(s): --foo

有些时候(例如:使用 parents),重写旧的有相同选项字符串的参数会更有用。为了产生这种行为, 'resolve' 值可以提供给 ArgumentParserconflict_handler= 参数:

1
2
3
4
5
6
7
8
9
10
>>> parser = argparse.ArgumentParser(prog='PROG', conflict_handler='resolve')
>>> parser.add_argument('-f', '--foo', help='old foo help')
>>> parser.add_argument('--foo', help='new foo help')
>>> parser.print_help()
usage: PROG [-h] [-f FOO] [--foo FOO]

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

注意: ArgumentParser 对象只能移除一个行为如果它所有的选项字符串都被重写。所以,在上面的例子中,旧的 -f/--foo 行为 回合 -f 行为保持一样, 因为只有 --foo 选项字符串被重写。

add_help

默认情况下,ArgumentParser 对象添加一个简单的显示解析器帮助信息的选项。举个例子,考虑一个名为 myprogram.py 的文件包含如下代码:

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

如果 -h or --help 在命令行中被提供, 参数解析器帮助信息会打印:

1
2
3
4
5
6
$ python myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]

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

有时候可能会需要关闭额外的帮助信息。这可以通过在 ArgumentParser 中设置 add_help= 参数为 False 来实现。

1
2
3
4
5
6
7
>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)
>>> parser.add_argument('--foo', help='foo help')
>>> parser.print_help()
usage: PROG [--foo FOO]

options:
--foo FOO foo help

帮助选项一般为 -h/--help。如果 prefix_chars= 被指定并且没有包含 - 字符,在这种情况下, -h --help 不是有效的选项。此时, prefix_chars 的第一个字符将用作帮助选项的前缀。

1
2
3
4
5
6
>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='+/')
>>> parser.print_help()
usage: PROG [+h]

options:
+h, ++help show this help message and exit

exit_on_error

正常情况下,当你向 ArgumentParserparse_args() 方法传入一个无效的参数列表时,它将会退出并发出错误信息。

如果用户想要手动捕获错误,可通过将 exit_on_error 设为 False 来启用该特性:

1
2
3
4
5
6
7
8
9
>>> parser = argparse.ArgumentParser(exit_on_error=False)
>>> parser.add_argument('--integers', type=int)
_StoreAction(option_strings=['--integers'], dest='integers', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)
>>> try:
... parser.parse_args('--integers a'.split())
... except argparse.ArgumentError:
... print('Catching an argumentError')
...
Catching an argumentError

3.9 新版功能.

添加参数 add_argument

给一个 ArgumentParser 添加程序参数信息是通过调用 add_argument() 方法完成的。通常,这些调用指定 ArgumentParser 如何获取命令行字符串并将其转换为对象。这些信息在 parse_args() 调用时被存储和使用。

例如:

1
2
3
4
5
>>> 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() 将返回一个具有 integersaccumulate 两个属性的对象。integers 属性将是一个包含一个或多个整数的列表,而 accumulate 属性当命令行中指定了 --sum 参数时将是 sum() 函数,否则则是 max() 函数。

  • add_argument() 方法
1
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() 的参数必须是一系列旗标或者是一个简单的参数名。例如,可选参数可以被这样创建:

1
parser.add_argument('-f', '--foo')

而位置参数可以这么创建:

1
parser.add_argument('bar')

parse_args() 被调用,选项会以 - 前缀识别,剩下的参数则会被假定为位置参数:

1
2
3
4
5
6
7
8
9
10
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-f', '--foo')
>>> parser.add_argument('bar')
>>> parser.parse_args(['BAR'])
Namespace(bar='BAR', foo=None)
>>> parser.parse_args(['BAR', '--foo', 'FOO'])
Namespace(bar='BAR', foo='FOO')
>>> parser.parse_args(['--foo', 'FOO'])
usage: PROG [-h] [-f FOO] bar
PROG: error: the following arguments are required: bar

action

ArgumentParser 对象将命令行参数与动作相关联。这些动作可以做与它们相关联的命令行参数的任何事,尽管大多数动作只是简单的向 parse_args() 返回的对象上添加属性。action 命名参数指定了这个命令行参数应当如何处理。供应的动作有:

  • store - 存储参数的值。这是默认的动作。例如:

    1
    2
    3
    4
    >>> parser = argparse.ArgumentParser()
    >>> parser.add_argument('--foo')
    >>> parser.parse_args('--foo 1'.split())
    Namespace(foo='1')
  • store_const - 存储被 const 命名参数指定的值。 store_const 动作通常用在选项中来指定一些标志。例如:

    1
    2
    3
    4
    >>> parser = 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 分别用作存储 TrueFalse 值的特殊用例。另外,它们的默认值分别为 FalseTrue。例如:

    1
    2
    3
    4
    5
    6
    >>> parser = 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
    4
    >>> parser = 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
    5
    >>> parser = 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
    4
    >>> parser = argparse.ArgumentParser()
    >>> parser.add_argument('--verbose', '-v', action='count', default=0)
    >>> parser.parse_args(['-vvv'])
    Namespace(verbose=3)

    请注意,default 将为 None,除非显式地设为 0

  • help - 打印所有当前解析器中的选项和参数的完整帮助信息,然后退出。默认情况下,一个 help 动作会被自动加入解析器。关于输出是如何创建的,参与 ArgumentParser

  • version - 期望有一个 version= 命名参数在 add_argument() 调用中,并打印版本信息并在调用后退出:

    1
    2
    3
    4
    5
    >>> import 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 - 这会存储一个列表,并将每个参数值加入到列表中。 示例用法:

    1
    2
    3
    4
    >>> parser = 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 子类或实现相同接口的其他对象来指定任意操作。 BooleanOptionalActionargparse 中可用并会添加对布尔型操作例如 --foo--no-foo 的支持:

1
2
3
4
5
>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action=argparse.BooleanOptionalAction)
>>> parser.parse_args(['--no-foo'])
Namespace(foo=False)

3.9 新版功能.

创建自定义动作的推荐方式是扩展 Action,重写 __call__ 方法以及可选的 __init__format_usage 方法。

一个自定义动作的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> class FooAction(argparse.Action):
... def __init__(self, option_strings, dest, nargs=None, **kwargs):
... if nargs is not None:
... raise ValueError("nargs not allowed")
... super().__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)
>>> parser.add_argument('bar', action=FooAction)
>>> args = parser.parse_args('1 --foo 2'.split())
Namespace(bar=None, foo=None) '1' None
Namespace(bar='1', foo=None) '2' '--foo'
>>> args
Namespace(bar='1', foo='2')

更多描述,见 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
    9
    >>> parser = 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
    11
    >>> parser = 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
    6
    >>> parser = 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
    7
    >>> parser = 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: foo

如果不提供 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

默认值

所有选项和一些位置参数可能在命令行中被忽略。add_argument() 的命名参数 default,默认值为 None,指定了在命令行参数未出现时应当使用的值。对于选项, default 值在选项未在命令行中出现时使用:

1
2
3
4
5
6
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default=42)
>>> parser.parse_args(['--foo', '2'])
Namespace(foo='2')
>>> parser.parse_args([])
Namespace(foo=42)

如果目标命名空间已经有一个属性集,则 default 动作不会覆盖它:

1
2
3
4
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default=42)
>>> parser.parse_args([], namespace=argparse.Namespace(foo=101))
Namespace(foo=101)

如果 default 值是一个字符串,解析器解析此值就像一个命令行参数。特别是,在将属性设置在 Namespace 的返回值之前,解析器应用任何提供的 type 转换参数。否则解析器使用原值:

1
2
3
4
5
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--length', default='10', type=int)
>>> parser.add_argument('--width', default=10.5, type=int)
>>> parser.parse_args()
Namespace(length=10, width=10.5)

对于 nargs 等于 ?* 的位置参数, default 值在没有命令行参数出现时使用。

1
2
3
4
5
6
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('foo', nargs='?', default=42)
>>> parser.parse_args(['a'])
Namespace(foo='a')
>>> parser.parse_args([])
Namespace(foo=42)

提供 default=argparse.SUPPRESS 导致命令行参数未出现时没有属性被添加:

1
2
3
4
5
6
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default=argparse.SUPPRESS)
>>> parser.parse_args([])
Namespace()
>>> parser.parse_args(['--foo', '1'])
Namespace(foo='1')

type

默认情况下,解析器会将命令行参数当作简单字符串读入。 然而,命令行字符串经常应当被解读为其他类型,例如 floatintadd_argument()type 关键字允许执行任何必要的类型检查和类型转换。

如果 type 关键字使用了 default关键字,则类型转换器仅会在默认值为字符串时被应用。

传给 type 的参数可以是任何接受单个字符串的可调用对象。 如果函数引发了 ArgumentTypeError, TypeErrorValueError,异常会被捕获并显示经过良好格式化的错误消息。 其他异常类型则不会被处理。

普通内置类型和函数可被用作类型转换器:

1
2
3
4
5
6
7
8
9
10
11
import argparse
import pathlib

parser = argparse.ArgumentParser()
parser.add_argument('count', type=int)
parser.add_argument('distance', type=float)
parser.add_argument('street', type=ascii)
parser.add_argument('code_point', type=ord)
parser.add_argument('source_file', type=open)
parser.add_argument('dest_file', type=argparse.FileType('w', encoding='latin-1'))
parser.add_argument('datapath', type=pathlib.Path)

用户自定义的函数也可以被使用:

1
2
3
4
5
6
7
>>> def hyphenated(string):
... return '-'.join([word[:4] for word in string.casefold().split()])
...
>>> parser = argparse.ArgumentParser()
>>> _ = parser.add_argument('short_title', type=hyphenated)
>>> parser.parse_args(['"The Tale of Two Cities"'])
Namespace(short_title='"the-tale-of-two-citi')

不建议将 bool()函数用作类型转换器。 它所做的只是将空字符串转为 False 而将非空字符串转为 True。 这通常不是用户所想要的。

通常,type 关键字是仅应被用于只会引发上述三种被支持的异常的简单转换的便捷选项。 任何具有更复杂错误处理或资源管理的转换都应当在参数被解析后由下游代码来完成。

例如,JSON 或 YAML 转换具有复杂的错误情况,要求给出比 type 关键字所能给出的更好的报告。 JSONDecodeError 将不会被良好地格式化而 FileNotFound 异常则完全不会被处理。

即使 FileType 在用于 type 关键字时也存在限制。 如果一个参数使用了 FileType 并且有一个后续参数出错,则将报告一个错误但文件并不会被自动关闭。 在此情况下,更好的做法是等待直到解析器运行完毕再使用 with 语句来管理文件。

对于简单地检查一组固定值的类型检查器,请考虑改用 choices 关键字。

choices

某些命令行参数应当从一组受限的值中选择。 这可以通过将一个序列对象作为 choices 关键字参数传给 add_argument() 来处理。 当执行命令行解析时,参数值将被检查,如果参数不是可接受的值之一就将显示错误消息:

1
2
3
4
5
6
7
8
>>> parser = argparse.ArgumentParser(prog='game.py')
>>> parser.add_argument('move', choices=['rock', 'paper', 'scissors'])
>>> parser.parse_args(['rock'])
Namespace(move='rock')
>>> parser.parse_args(['fire'])
usage: game.py [-h] {rock,paper,scissors}
game.py: error: argument move: invalid choice: 'fire' (choose from 'rock',
'paper', 'scissors')

请注意 choices 序列包含的内容会在执行任意 type 转换之后被检查,因此 choices 序列中对象的类型应当与指定的 type 相匹配:

1
2
3
4
5
6
7
>>> parser = argparse.ArgumentParser(prog='doors.py')
>>> parser.add_argument('door', type=int, choices=range(1, 4))
>>> print(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)

任何序列都可作为 choices 值传入,因此 list 对象、tuple 对象以及自定义序列都是受支持的。

不建议使用 enum.Enum,因为要控制其在用法、帮助和错误消息中的外观是很困难的。

已格式化的选项会覆盖默认的 metavar,该值一般是派生自 dest。 这通常就是你所需要的,因为用户永远不会看到 dest 形参。 如果不想要这样的显示(或许因为有很多选择),只需指定一个显式的 metavar。

required

通常,argparse 模块会认为 -f--bar 等旗标是指明 可选的 参数,它们总是可以在命令行中被忽略。 要让一个选项成为 必需的,则可以将 True 作为 required= 关键字参数传给 add_argument():

1
2
3
4
5
6
7
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', required=True)
>>> parser.parse_args(['--foo', 'BAR'])
Namespace(foo='BAR')
>>> parser.parse_args([])
usage: [-h] --foo FOO
: error: the following arguments are required: --foo

如这个例子所示,如果一个选项被标记为 required,则当该选项未在命令行中出现时,parse_args() 将会报告一个错误。

注解: 必需的选项通常被认为是不适宜的,因为用户会预期 options 都是 可选的,因此在可能的情况下应当避免使用它们。

help

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('--foo', action='store_true',
... help='foo the bars before frobbling')
>>> parser.add_argument('bar', nargs='+',
... help='one of the bars to be frobbled')
>>> parser.parse_args(['-h'])
usage: frobble [-h] [--foo] bar [bar ...]

positional arguments:
bar one of the bars to be frobbled

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

help 字符串可包括各种格式描述符以避免重复使用程序名称或参数 default 等文本。 有效的描述符包括程序名称 %(prog)s 和传给 add_argument() 的大部分关键字参数,例如 %(default)s, %(type)s 等等:

1
2
3
4
5
6
7
8
9
10
11
>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('bar', nargs='?', type=int, default=42,
... help='the bar to %(prog)s (default: %(default)s)')
>>> parser.print_help()
usage: frobble [-h] [bar]

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

options:
-h, --help show this help message and exit

由于帮助字符串支持 %-formatting,如果你希望在帮助字符串中显示 % 字面值,你必须将其转义为 %%

argparse 支持静默特定选项的帮助,具体做法是将 help 的值设为 argparse.SUPPRESS:

1
2
3
4
5
6
7
>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('--foo', help=argparse.SUPPRESS)
>>> parser.print_help()
usage: frobble [-h]

options:
-h, --help show this help message and exit

metavar

ArgumentParser 生成帮助消息时,它需要用某种方式来引用每个预期的参数。 默认情况下,ArgumentParser 对象使用 dest 值作为每个对象的 “name”。 默认情况下,对于位置参数动作,dest 值将被直接使用,而对于可选参数动作,dest 值将被转为大写形式。 因此,一个位置参数 dest='bar' 的引用形式将为 bar。 一个带有单独命令行参数的可选参数 --foo 的引用形式将为 FOO。 示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
>>> parser.add_argument('bar')
>>> parser.parse_args('X --foo Y'.split())
Namespace(bar='X', foo='Y')
>>> parser.print_help()
usage: [-h] [--foo FOO] bar

positional arguments:
bar

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

可以使用 metavar 来指定一个替代名称:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', metavar='YYY')
>>> parser.add_argument('bar', 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

options:
-h, --help show this help message and exit
--foo YYY

请注意 metavar 仅改变 显示的 名称 - parse_args()对象的属性名称仍然会由 dest 值确定。

不同的 nargs 值可能导致 metavar 被多次使用。 提供一个元组给 metavar 即为每个参数指定不同的显示信息:

1
2
3
4
5
6
7
8
9
10
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x', nargs=2)
>>> parser.add_argument('--foo', nargs=2, metavar=('bar', 'baz'))
>>> parser.print_help()
usage: PROG [-h] [-x X X] [--foo bar baz]

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

dest

大多数 ArgumentParser 动作会添加一些值作为 parse_args() 所返回对象的一个属性。 该属性的名称由 add_argument()dest 关键字参数确定。 对于位置参数动作,dest 通常会作为 add_argument() 的第一个参数提供:

1
2
3
4
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('bar')
>>> parser.parse_args(['XXX'])
Namespace(bar='XXX')

对于可选参数动作,dest 的值通常取自选项字符串。 ArgumentParser 会通过接受第一个长选项字符串并去掉开头的 -- 字符串来生成 dest 的值。 如果没有提供长选项字符串,则 dest 将通过接受第一个短选项字符串并去掉开头的 - 字符来获得。 任何内部的 - 字符都将被转换为 _ 字符以确保字符串是有效的属性名称。 下面的例子显示了这种行为:

1
2
3
4
5
6
7
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-f', '--foo-bar', '--foo')
>>> parser.add_argument('-x', '-y')
>>> 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')

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

1
2
3
4
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', dest='bar')
>>> parser.parse_args('--foo XXX'.split())
Namespace(bar='XXX')

Action 类

Action 类实现了 Action API,它是一个返回可调用对象的可调用对象,返回的可调用对象可处理来自命令行的参数。 任何遵循此 API 的对象均可作为 action 形参传给 add_argument()

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

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

Action 的实例(或作为or return value of any callable to the action 形参的任何可调用对象的返回值)应当定义 “dest”, “option_strings”, “default”, “type”, “required”, “help” 等属性。 确保这些属性被定义的最容易方式是调用 Action.__init__

Action 的实例应当为可调用对象,因此所有子类都必须重写 __call__ 方法,该方法应当接受四个形参:

  • parser - 包含此动作的 ArgumentParser 对象。
  • namespace - 将由 parse_args() 返回的 Namespace 对象。 大多数动作会使用 setattr() 为此对象添加属性。
  • values - 已关联的命令行参数,并提供相应的类型转换。 类型转换由 add_argument() 的 type 关键字参数来指定。
  • option_string - 被用来发起调用此动作的选项字符串。 option_string 参数是可选的,且此参数在动作关联到位置参数时将被略去。

__call__ 方法可以执行任意动作,但通常将基于 destvalues 来设置 namespace 的属性。

动作子类可定义 format_usage 方法,该方法不带参数,所返回的字符串将被用于打印程序的用法说明。 如果未提供此方法,则将使用适当的默认值。

解析参数 parse_args()

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

1
parser.parse_args(['--sum', '7', '-1', '42'])

在脚本中,通常 parse_args() 会被不带参数调用,而 ArgumentParser 将自动从 sys.argv 中确定命令行参数。

parse_args()

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

    将参数字符串转换为对象并将其设为命名空间的属性。 返回带有成员的命名空间。

    之前对 add_argument() 的调用决定了哪些对象被创建以及它们如何被赋值。 请参阅 add_argument() 的文档了解详情。

    • args - 要解析的字符串列表。 默认值是从 sys.argv 获取。

    • namespace - 用于获取属性的对象。 默认值是一个新的空 Namespace 对象。

选项值语法

parse_args() 方法支持多种指定选项值的方式(如果它接受选项的话)。在最简单的情况下,选项和它的值是作为两个单独参数传入的:

1
2
3
4
5
6
7
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x')
>>> parser.add_argument('--foo')
>>> parser.parse_args(['-x', 'X'])
Namespace(foo=None, x='X')
>>> parser.parse_args(['--foo', 'FOO'])
Namespace(foo='FOO', x=None)

对于长选项(名称长度超过一个字符的选项),选项和值也可以作为单个命令行参数传入,使用 = 分隔它们即可:

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

对于短选项(长度只有一个字符的选项),选项和它的值可以拼接在一起:

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

有些短选项可以使用单个 - 前缀来进行合并,如果仅有最后一个选项(或没有任何选项)需要值的话:

1
2
3
4
5
6
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x', action='store_true')
>>> parser.add_argument('-y', action='store_true')
>>> parser.add_argument('-z')
>>> parser.parse_args(['-xyzZ'])
Namespace(x=True, y=True, z='Z')

无效的参数

在解析命令行时,parse_args() 会检测多种错误,包括有歧义的选项、无效的类型、无效的选项、错误的位置参数个数等等。 当遇到这种错误时,它将退出并打印出错误文本同时附带用法消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo', type=int)
>>> parser.add_argument('bar', nargs='?')

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

>>> # invalid option
>>> parser.parse_args(['--bar'])
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: no such option: --bar

>>> # wrong number of arguments
>>> parser.parse_args(['spam', 'badger'])
usage: PROG [-h] [--foo FOO] [bar]
PROG: error: extra arguments found: badger

包含 - 的参数

parse_args() 方法会在用户明显出错时尝试给出错误信息,但某些情况本身就存在歧义。 例如,命令行参数 -1 可能是尝试指定一个选项也可能是尝试提供一个位置参数。 parse_args() 方法在此会谨慎行事:位置参数只有在它们看起来像负数并且解析器中没有任何选项看起来像负数时才能以 - 打头。:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x')
>>> parser.add_argument('foo', nargs='?')

>>> # no negative number options, so -1 is a positional argument
>>> parser.parse_args(['-x', '-1'])
Namespace(foo=None, x='-1')

>>> # no negative number options, so -1 and -5 are positional arguments
>>> parser.parse_args(['-x', '-1', '-5'])
Namespace(foo='-5', x='-1')

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-1', dest='one')
>>> parser.add_argument('foo', nargs='?')

>>> # negative number options present, so -1 is an option
>>> parser.parse_args(['-1', 'X'])
Namespace(foo=None, one='X')

>>> # negative number options present, so -2 is an option
>>> parser.parse_args(['-2'])
usage: PROG [-h] [-1 ONE] [foo]
PROG: error: no such option: -2

>>> # negative number options present, so both -1s are options
>>> parser.parse_args(['-1', '-1'])
usage: PROG [-h] [-1 ONE] [foo]
PROG: error: argument -1: expected one argument

如果你有必须以 - 打头的位置参数并且看起来不像负数,你可以插入伪参数 '--' 以告诉 parse_args() 在那之后的内容是一个位置参数:

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

参数缩写(前缀匹配)

parse_args() 方法 在默认情况下 允许将长选项缩写为前缀,如果缩写无歧义(即前缀与一个特定选项相匹配)的话:

1
2
3
4
5
6
7
8
9
10
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-bacon')
>>> parser.add_argument('-badger')
>>> 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 -badger, -bacon

可产生一个以上选项的参数会引发错误。 此特定可通过将 allow_abbrev 设为 False 来禁用。

sys.argv 以外

有时在 sys.argv 以外用 ArgumentParser 解析参数也是有用的。 这可以通过将一个字符串列表传给 parse_args() 来实现。 它适用于在交互提示符下进行检测:

1
2
3
4
5
6
7
8
9
10
11
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument(
... 'integers', metavar='int', type=int, choices=range(10),
... nargs='+', help='an integer in the range 0..9')
>>> parser.add_argument(
... '--sum', dest='accumulate', action='store_const', const=sum,
... default=max, help='sum the integers (default: find the max)')
>>> 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])

命名空间对象

  • class argparse.``Namespace

    parse_args() 默认使用的简单类,可创建一个存放属性的对象并将其返回。

这个类被有意做得很简单,只是一个具有可读字符串表示形式的 object。 如果你更喜欢类似字典的属性视图,你可以使用标准 Python 中惯常的 vars():

1
2
3
4
5
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
>>> args = parser.parse_args(['--foo', 'BAR'])
>>> vars(args)
{'foo': 'BAR'}

另一个用处是让 ArgumentParser 为一个已存在对象而不是为一个新的 Namespace 对象的属性赋值。 这可以通过指定 namespace= 关键字参数来实现:

1
2
3
4
5
6
7
8
9
>>> class C:
... pass
...
>>> c = C()
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
>>> parser.parse_args(args=['--foo', 'BAR'], namespace=c)
>>> c.foo
'BAR'

示例

以下代码是一个 Python 程序,它获取一个整数列表并计算总和或者最大值:

1
2
3
4
5
6
7
8
9
10
11
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 的文件中,它可以在命令行运行并提供有用的帮助信息:

1
2
3
4
5
6
7
8
9
10
11
$ python prog.py -h
usage: prog.py [-h] [--sum] N [N ...]

Process some integers.

positional arguments:
N an integer for the accumulator

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

当使用适当的参数运行时,它会输出命令行传入整数的总和或者最大值:

1
2
3
4
5
$ python prog.py 1 2 3 4
4

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

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

1
2
3
$ python prog.py a b c
usage: prog.py [-h] [--sum] N [N ...]
prog.py: error: argument N: invalid int value: 'a'

参考资料



文章链接:
https://www.zywvvd.com/notes/coding/python/python-argparse/python-argparse/


“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

Python argparse 教程
https://www.zywvvd.com/notes/coding/python/python-argparse/python-argparse/
作者
Yiwei Zhang
发布于
2024年12月27日
许可协议