# `argparse` --- 用于命令行选项、参数和子命令的解析器

Added in version 3.2.

源代码： Lib/argparse.py

备注

虽然 `argparse` 是推荐的用于实现基本命令行应用程序的标准库模块，但对于命令行应用程序的行为有更明确的要求的开发者可能会发现它并未提供所需层次的控制能力。 请参阅 选择参数解析库 了解当 `argparse` 不支持特定应用程序需要的行为（例如完全禁用散开选项和位置参数，或接受以 `-` 开头的选项形参值即使它们对应了其它已定义的选项）时可以考虑的替代。

`argparse` 模块让编写用户友好的命令行接口变得容易。 程序定义它需要哪些参数，`argparse` 将会知道如何从 `sys.argv` 解析它们。 `argparse` 模块还能自动生成帮助和用法消息文本。 该模块还会在用户向程序传入无效参数时发出错误提示。

`argparse` 模块对命令行界面的支持是围绕 `argparse.ArgumentParser` 实例建立的。 它是一个用于参数规格说明的容器并包含应用于解析器的一组选项:

    parser = argparse.ArgumentParser(
                        prog='ProgramName',
                        description='What the program does',
                        epilog='Text at the bottom of help')

`ArgumentParser.add_argument()` 方法将单个参数规格说明关联到解析器。 它支持位置参数，接受各种值的选项，以及各种启用/禁用旗标:

    parser.add_argument('filename')           # 位置参数
    parser.add_argument('-c', '--count')      # 接受一个值的选项
    parser.add_argument('-v', '--verbose',
                        action='store_true')  # 启用/禁用旗标

`ArgumentParser.parse_args()` 方法运行解析器并将提取的数据放入 `argparse.Namespace` 对象:

    args = parser.parse_args()
    print(args.filename, args.count, args.verbose)

备注

如果您正在寻找如何将 `optparse` 代码升级到 `argparse` 的指南，请参阅 Upgrading Optparse Code。

## ArgumentParser 对象

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

  创建一个新的 `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` 根据Python 解释器 的运行方式，计算出要在帮助信息中显示的程序名称：

- 如果作为参数传递的是文件，则是``sys.argv[0]`` 的 `base name` 。

- 如果作为参数传递的是目录或 ZIP 文件，则是Python 解释器名称，后接 `sys.argv[0]`。

- 如果使用 `-m` 选项则是在 Python 解释器名称后接 `-m` 再加模块或包的名称。

默认行为几乎总是符合需求因为它将使帮助消息与在命令行上唤起程序所用的字符串相匹配。 不过，要更改此默认行为，可以将 `prog=` 参数传入 `ArgumentParser` 以提供另外的值:

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

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

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

    >>> parser = argparse.ArgumentParser(prog='myprogram')
    >>> parser.add_argument('--foo', help='foo of the %(prog)s program')
    >>> parser.print_help()
    usage: myprogram [-h] [--foo FOO]

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

### usage（用法）

默认情况下，`ArgumentParser` 会从它所包含的参数中计算出用法消息。 默认消息可以通过 `usage=` 关键字参数进行覆盖。

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

    positional arguments:
     bar          bar help

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

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

### description（描述）

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

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

### epilog

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

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

    A foo that bars

    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` 对象。

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

`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

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

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

传 `RawDescriptionHelpFormatter` 给 `formatter_class=` 表示 description 和 epilog 已经被正确的格式化了，不能在命令行中被自动换行:

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

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

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

`RawTextHelpFormatter` 保留各种帮助文本的空白符，包括参数描述。 但是，多个换行符会被替换为一个。 如果你希望保留多个空行，请在换行符之间添加空格。

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

    >>> parser = argparse.ArgumentParser(
    ...     prog='PROG',
    ...     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    >>> parser.add_argument('--foo', type=int, default=42, help='FOO!')
    >>> parser.add_argument('bar', nargs='*', default=[1, 2, 3], help='BAR!')
    >>> parser.print_help()
    usage: PROG [-h] [--foo FOO] [bar ...]

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

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

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

    >>> parser = argparse.ArgumentParser(
    ...     prog='PROG',
    ...     formatter_class=argparse.MetavarTypeHelpFormatter)
    >>> parser.add_argument('--foo', type=int)
    >>> parser.add_argument('bar', type=float)
    >>> parser.print_help()
    usage: PROG [-h] [--foo int] float

    positional arguments:
      float

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

### prefix_chars

大多数命令行选项会使用 `-` 作为前缀，例如 `-f/--foo`。 如果解析器需要支持不同的或者额外的前缀字符，例如像 `+f` 或 `/foo` 之类的选项，可以在 `ArgumentParser` 构造器中使用 `prefix_chars=` 参数来指定它们:

    >>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+')
    >>> parser.add_argument('+f')
    >>> parser.add_argument('++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` 构造器，则任何以指定字符打头的参数都将被当作文件来处理，并将被它们包含的参数所替代。 举例来说:

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

Arguments read from a file must be one per line by default (but see also `convert_arg_line_to_args()`) and are treated as if they were in the same place as the original file referencing argument on the command line. So in the example above, the expression `['-f', 'foo', '@args.txt']` is considered equivalent to the expression `['-f', 'foo', '-f', 'bar']`.

备注

Empty lines are treated as empty strings (`''`), which are allowed as values but not as arguments. Empty lines that are read as arguments will result in an "unrecognized arguments" error.

`ArgumentParser` 使用 filesystem encoding and error handler 来读取包含参数的文件。

`fromfile_prefix_chars=` 参数默认为 `None`，意味着参数不会被当作文件对待。

在 3.12 版本发生变更: `ArgumentParser` 将读取参数的编码格式和错误处理方式从默认值 (即 `locale.getpreferredencoding(False)` 和 `"strict"`) 改为 filesystem encoding and error handler。 在 Windows 上参数文件应当以 UTF-8 而不是 ANSI 代码页来编码。

### argument_default

一般情况下，参数默认会通过设置一个默认到 `add_argument()` 或者调用带一组指定键值对的 `ArgumentParser.set_defaults()` 方法。但是有些时候，为参数指定一个普遍适用的解析器会更有用。这能够通过传输 `argument_default=` 关键词参数给 `ArgumentParser` 来完成。举个栗子，要全局禁止在 `parse_args()` 中创建属性，我们提供 `argument_default=SUPPRESS`:

    >>> parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
    >>> parser.add_argument('--foo')
    >>> parser.add_argument('bar', nargs='?')
    >>> parser.parse_args(['--foo', '1', 'BAR'])
    Namespace(bar='BAR', foo='1')
    >>> parser.parse_args([])
    Namespace()

### allow_abbrev

正常情况下，当你向 `ArgumentParser` 的 `parse_args()` 方法传入一个参数列表时，它会 recognizes abbreviations。

这个特性可以设置 `allow_abbrev` 为 `False` 来关闭:

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

Added in version 3.5.

### conflict_handler

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

    >>> 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'` 值可以提供给 `ArgumentParser` 的 `conflict_handler=` 参数:

    >>> 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` 对象会添加一个简单地显示解析器的帮助消息的选项。 如果在命令行中提供了 `-h` 或 `--help`，则会打印 `ArgumentParser` 帮助消息。

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

    >>> 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` 的第一个字符将用作帮助选项的前缀。

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

通常，当你向 `ArgumentParser` `parse_args()` 方法传入一个无效的参数列表时，它会将 message 打印到 `sys.stderr` 并附带状态码 2 退出程序。

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

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

Added in version 3.9.

## add_argument() 方法

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

  定义单个的命令行参数应当如何解析。每个形参都在下面有它自己更多的描述，长话短说有：

  - name or flags - 一个名称或是由选项字符串组成的列表，例如 `'foo'` 或 `'-f', '--foo'`。

  - action - 当参数在命令行中出现时使用的动作基本类型。

  - nargs - 命令行参数应当消耗的数目。

  - const - 被一些 action 和 nargs 选择所需求的常数。

  - default - 当参数未在命令行中出现并且也不存在于命名空间对象时所产生的值。

  - type - 命令行参数应当被转换成的类型。

  - choices - 由允许作为参数的值组成的序列。

  - required - 此命令行选项是否可省略 （仅选项可用）。

  - help - 一个此选项作用的简单描述。

  - metavar - 在使用方法消息中使用的参数值示例。

  - dest - 被添加到 `parse_args()` 所返回对象上的属性名。

  - deprecated - 参数的使用是否已被弃用。

以下部分描述这些参数如何使用。

### name or flags

`add_argument()` 方法必须知道是要接收一个可选参数，如 `-f` 或 `--foo`，还是一个位置参数，如由文件名组成的列表。 因此首先传递给 `add_argument()` 的参数必须是一组旗标，或一个简单的参数名称。

例如，可以这样创建可选参数:

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

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

    >>> parser.add_argument('bar')

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

    >>> 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'` - 这用于存储参数的值。 这是默认的动作。

- `'store_const'` - 存储由 const 关键字参数指定的值；请注意 const 关键字参数默认为 `None`。 `'store_const'` 动作最常被用于指定某类旗标的可选参数。 例如:

      >>> parser = argparse.ArgumentParser()
      >>> parser.add_argument('--foo', action='store_const', const=42)
      >>> parser.parse_args(['--foo'])
      Namespace(foo=42)

- `'store_true'` 和 `'store_false'` - 这些是 `'store_const'` 的特例，分别用于存储 `True` 和 `False` 值。 此外，它们还会分别创建默认的 `False` 和 `True` 值:

      >>> 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'` - 存储一个列表，并将每个参数值添加到该列表。 它适用于允许可多次指定的选项。 如果默认值非空，则默认的元素将出现在该选项的已解析值中，并将所有来自命令行的值添加在默认值之后。 示例用法:

      >>> 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'` 动作通常适用于多个参数需要将常量存储到同一列表的场合。 例如:

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

- `'extend'` - 这将存储一个列表并添加来自于多值参数列表的每个条目。 `'extend'` 动作通常配合 nargs 关键字参数值 `'+'` 或 `'*'` 使用。 请注意当 nargs 为 `None` (默认值) 或 `'?'` 时，将把参数字符串中的每个字符添加到列表。 示例用法:

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

  Added in version 3.8.

- `'count'` - 计算一个关键字参数出现的数目或次数。例如，对于一个增长的详情等级来说有用:

      >>> 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()` 调用中，并打印版本信息并在调用后退出:

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

你也可以通过传入一个 `Action` 子类 (例如 `BooleanOptionalAction`) 或其他实现了相同接口的对象指定任意的动作。 只有消费命令行参数的动作 (例如 `'store'`, `'append'`, `'extend'` 或具有非零 `nargs` 的自定义动作) 可配合位置参数使用。

创建自定义动作的推荐方式是扩展 `Action`，重写 `__call__()` 方法以及可选的 `__init__()` 和 `format_usage()` 方法。 你还可以使用 `register()` 方法注册自定义动作并通过其注册名称来引用它们。

一个自定义动作的例子:

    >>> 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` 个参数会被聚集到一个列表中。 例如:

      >>> 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 值。 一些说明这种情况的例子如下:

      >>> 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='?'` 的一个更普遍用法是允许可选的输入或输出文件:

      >>> 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='*'` 来实现多个位置参数通常没有意义，但是多个选项是可能的。例如:

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

- `'+'`。 和 `'*'` 类似，所有当前命令行参数被聚集到一个列表中。 另外，如果不存在至少一个命令行参数则会生成一条错误消息。 例如:

      >>> 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 来确定。 通常这意味着消耗一个命令行参数并产生一个条目（而非列表）。 不消耗命令行参数的动作 (例如 `'store_const'`) 则要设置 `nargs=0`。

### const

`add_argument()` 的 `const` 参数用于保存不从命令行中读取但被各种 `ArgumentParser` 动作需求的常数值。最常用的两例为：

- 当 `add_argument()` 附带 `action='store_const'` 或 `action='append_const'` 被调用时。 这些动作会把 `const` 值添加到 `parse_args()` 所返回的对象的属性中。 请查看 action 的示例描述。 如果未将 `const` 提供给 `add_argument()`，它将接收一个 `None` 的默认值。

- 当 `add_argument()` 附带选项字符串 (如 `-f` 或 `--foo`) 和 `nargs='?'` 被调用的时候。 这会创建一个可以跟随零到一个命令行参数的选项参数。 当解析该命令行时，如果选项字符串没有跟随任何命令行参数，`const` 的值将被假定为以 `None` 代替。 请参阅 nargs 描述中的示例。

在 3.11 版本发生变更: 在默认情况下 `const=None`，包括 `action='append_const'` 或 `action='store_const'` 的时候。

### 默认值

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

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

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

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

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

    >>> 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` 值在没有命令行参数出现时使用。

    >>> parser = argparse.ArgumentParser()
    >>> parser.add_argument('foo', nargs='?', default=42)
    >>> parser.parse_args(['a'])
    Namespace(foo='a')
    >>> parser.parse_args([])
    Namespace(foo=42)

对于 required 参数， `default` 值将被忽略。 例如，这将适用于带有 `?` 和 `*` 以外的 nargs 值的位置参数，或者被标记为 `required=True` 的可选参数。

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

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

### type -- 类型

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

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

传给 `type` 的参数可以是接受一个字符串或一个已注册类型名称 (参见 `register()`) 的可调用对象。 如果该函数引发了 `ArgumentTypeError`, `TypeError` 或 `ValueError`，异常将被捕获并显示经良好格式化的错误消息。 其他异常类型则不会被处理。

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

    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('dest_file', type=argparse.FileType('w', encoding='latin-1'))
    parser.add_argument('datapath', type=pathlib.Path)

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

    >>> 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` 将不会被良好地格式化而 `FileNotFoundError` 异常则完全不会被处理。

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

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

### choices

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

    >>> 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 相匹配。

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

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

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

### required

通常，`argparse` 模块会假定像 `-f` 和 `--bar` 这样的旗标是表示 可选 参数，它们总是可以在命令行中被省略。 要让一个选项成为 必需，则可以将 `True` 作为 `required=` 关键字参数传给 `add_argument()`:

    >>> 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` 描述信息将随每个参数一同显示。

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

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

    >>> 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 值作为每个对象的“名字”。 默认情况下，对于位置参数动作，dest 值将被直接使用，而对于可选参数动作，dest 值将被转为大写形式。 因此，对于 `dest='bar'` 位置参数的引用形式将为 `bar`。 带有单个命令行参数的可选参数 `--foo` 的引用形式将为 `FOO`。 一个样例:

    >>> 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` 来指定一个替代名称:

    >>> 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` 即为每个参数指定不同的显示信息:

    >>> 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()` 的第一个参数提供:

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

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

    >>> 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` 允许提供自定义属性名称:

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

### deprecated

在一个项目的生命期内，某些命令行参数可能需要被移除。 在移除它们之前，你应当通知你的用户这些参数已被弃用并将被移除。 `add_argument()` 的 `deprecated` 关键字参数指明参数已被弃用并将在未来被移除，其默认值为 `False`。 对于每个参数，如果 `deprecated` 为 `True`，那么当该参数被使用时会打印一条警告到 `sys.stderr`:

    >>> import argparse
    >>> parser = argparse.ArgumentParser(prog='snake.py')
    >>> parser.add_argument('--legs', default=0, type=int, deprecated=True)
    >>> parser.parse_args([])
    Namespace(legs=0)
    >>> parser.parse_args(['--legs', '4'])
    snake.py: warning: option '--legs' is deprecated
    Namespace(legs=4)

Added in version 3.13.

### 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` 的实例（或作为 `action` 形参的任何可调用对象的返回值）应当定义 `dest`, `option_strings`, `default`, `type`, `required`, `help` 等属性。 确定这些属性的最容易的方式是调用 `Action.__init__()`。

  __call__(parser, namespace, values, option_string=None)

    `Action` 的实例应当为可调用对象，因此所有子类都必须重写 `__call__()` 方法，它应当接受四个形参：

    - parser - 包含此动作的 `ArgumentParser` 对象。

    - namespace - 将由 `parse_args()` 返回的 `Namespace` 对象。 大多数动作会使用 `setattr()` 为此对象添加一个属性。

    - values - 关联的命令行参数，并提供要应用的类型转换。 类型转换是由传给 `add_argument()` 的 type 关键字参数指定的。

    - option_string - 被用于唤起此动作的选项字符串。 `option_string` 参数是可选的，并且在动作被关联到位置参数时将被略去。

    `__call__()` 方法可以执行任意动作，但通常将基于 `dest` 和 `values` 来设置 `namespace` 的属性。

  format_usage()

    `Action` 子类可以定义 `format_usage()` 方法，该方法不接受任何参数并返回一个将被用于打印程序的用法说明的字符串。 如果未提供此方法，则将使用适当的默认值。

class argparse.BooleanOptionalAction

  一个继承自 `Action` 的子类，专门用于处理带有正负选项的布尔标志。 当添加类似 `--foo` 的单个参数时，该子类会自动同时创建 `--foo` 和 `--no-foo` 两个选项，并分别存储 `True` 和 `False` 值:

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

  Added in version 3.9.

## parse_args() 方法

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

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

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

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

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

### 选项值语法

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

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

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

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

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

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

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

    >>> 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()` 会检测多种错误，包括有歧义的选项、无效的类型、无效的选项、错误的位置参数个数等等。 当遇到这种错误时，它将退出并打印出错误文本同时附带用法消息:

    >>> 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()` 方法在此会谨慎行事：位置参数只有在它们看起来像负数并且解析器中没有任何选项看起来像负数时才能以 `-` 打头。:

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

    >>> # 没有负数选项，因此 -1 是位置参数
    >>> parser.parse_args(['-x', '-1'])
    Namespace(foo=None, x='-1')

    >>> # 没有负数选项，因此 -1 和 -5 是位置参数
    >>> 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='?')

    >>> # 有负数选项，因此 -1 是选项
    >>> parser.parse_args(['-1', 'X'])
    Namespace(foo=None, one='X')

    >>> # 有负数选项，因此 -2 是选项
    >>> parser.parse_args(['-2'])
    usage: PROG [-h] [-1 ONE] [foo]
    PROG: error: no such option: -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)

另请参阅 针对有歧义参数的 argparse 指引 来了解更多细节。

### 参数缩写（前缀匹配）

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

    >>> 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()` 来实现。 它适用于在交互提示符下进行测试:

    >>> 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()`:

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

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

      >>> class C:
      ...     pass
      ...
      >>> c = C()
      >>> parser = argparse.ArgumentParser()
      >>> parser.add_argument('--foo')
      >>> parser.parse_args(args=['--foo', 'BAR'], namespace=c)
      >>> c.foo
      'BAR'

## 其它实用工具

### 子命令

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

  许多程序都将其功能拆分为一系列子命令，例如，`svn` 程序可唤起像 `svn checkout`, `svn update` 和 `svn commit` 等子命令。 当一个程序执行需要多组不同各类命令行参数时这种拆分功能的方式是一个非常好的主意。 `ArgumentParser` 通过 `add_subparsers()` 方法支持创建这样的子命令。 `add_subparsers()` 方法通常不带参数地调用并返回一个特殊的动作对象。 该对象只有一个方法 `add_parser()`，它接受一个命令名称和任意多个 `ArgumentParser` 构造器参数，并返回一个可以通常方式进行修改的 `ArgumentParser` 对象。

  形参的描述

  - title - 帮助输出中子解析器分组的标题；如果提供了描述则默认为 "subcommands"，否则使用位置参数的标题

  - description - 帮助输出中对子解析器组的描述，默认为 `None`

  - prog - 将与子命令帮助一同显示的用法信息，默认为程序名称和子解析器参数之前的任何位置参数

  - parser_class - 将被用于创建子解析器实例的类，默认为当前解析器类 (例如 `ArgumentParser`)

  - action - 当此参数在命令行中出现时要执行动作的基本类型

  - dest - 将被用于保存子命令名称的属性名；默认为 `None` 即不保存任何值

  - required - 是否必须要提供子命令，默认为 `False` (在 3.7 中新增)

  - help - 在输出帮助中的子解析器分组帮助信息，默认为 `None`

  - metavar - 帮助信息中表示可用子命令的字符串；默认为 `None` 并以 {cmd1, cmd2, ..} 的形式表示子命令

  一些使用示例:

      >>> # 创建一个最高层级解析器
      >>> parser = argparse.ArgumentParser(prog='PROG')
      >>> parser.add_argument('--foo', action='store_true', help='foo help')
      >>> subparsers = parser.add_subparsers(help='subcommand help')
      >>>
      >>> # 创建一个针对 "a" 命令的解析器
      >>> parser_a = subparsers.add_parser('a', help='a help')
      >>> parser_a.add_argument('bar', type=int, help='bar help')
      >>>
      >>> # 创建一个针对 "b" 命令的解析器
      >>> parser_b = subparsers.add_parser('b', help='b help')
      >>> parser_b.add_argument('--baz', choices=('X', 'Y', 'Z'), help='baz help')
      >>>
      >>> # 解析一些参数列表
      >>> parser.parse_args(['a', '12'])
      Namespace(bar=12, foo=False)
      >>> parser.parse_args(['--foo', 'b', '--baz', 'Z'])
      Namespace(baz='Z', foo=True)

  请注意 `parse_args()` 返回的对象将只包含主解析器和由命令行所选择的子解析器的属性（而没有任何其他子解析器）。 因此在上面的例子中，当指定了 `a` 命令时，将只存在 `foo` 和 `bar` 属性，而当指定了 `b` 命令时，则只存在 `foo` 和 `baz` 属性。

  类似地，当一个子解析器请求帮助消息时，只有该特定解析器的帮助消息会被打印出来。 帮助消息将不包括父解析器或同级解析器的消息。 （每个子解析器命令一条帮助消息，但是，也可以像上面那样通过将 `help=` 参数传入 `add_parser()` 来给出。）

      >>> parser.parse_args(['--help'])
      usage: PROG [-h] [--foo] {a,b} ...

      positional arguments:
        {a,b}   subcommand help
          a     a help
          b     b help

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

      >>> parser.parse_args(['a', '--help'])
      usage: PROG a [-h] bar

      positional arguments:
        bar     bar help

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

      >>> parser.parse_args(['b', '--help'])
      usage: PROG b [-h] [--baz {X,Y,Z}]

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

  `add_subparsers()` 方法也支持 `title` 和 `description` 关键字参数。 当两者都存在时，子解析器的命令将出现在输出帮助消息中它们自己的分组内。 例如:

      >>> parser = argparse.ArgumentParser()
      >>> subparsers = parser.add_subparsers(title='subcommands',
      ...                                    description='valid subcommands',
      ...                                    help='additional help')
      >>> subparsers.add_parser('foo')
      >>> subparsers.add_parser('bar')
      >>> parser.parse_args(['-h'])
      usage:  [-h] {foo,bar} ...

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

      subcommands:
        valid subcommands

        {foo,bar}   additional help

  此外，`add_parser()` 还支持附加的 aliases 参数，它允许多个字符串指向同一个子解析器。 下面的例子，类似于 `svn`，将别名 `co` 设为 `checkout` 的缩写形式:

      >>> parser = argparse.ArgumentParser()
      >>> subparsers = parser.add_subparsers()
      >>> checkout = subparsers.add_parser('checkout', aliases=['co'])
      >>> checkout.add_argument('foo')
      >>> parser.parse_args(['co', 'bar'])
      Namespace(foo='bar')

  `add_parser()` 也支持附加的 deprecated 参数，它允许弃用子解析器。

      >>> import argparse
      >>> parser = argparse.ArgumentParser(prog='chicken.py')
      >>> subparsers = parser.add_subparsers()
      >>> run = subparsers.add_parser('run')
      >>> fly = subparsers.add_parser('fly', deprecated=True)
      >>> parser.parse_args(['fly'])
      chicken.py: warning: command 'fly' is deprecated
      Namespace()

  Added in version 3.13.

  一个特别有效的处理子命令的方式是将 `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(required=True)
      >>>
      >>> # 创建针对 "foo" 命令的解析器
      >>> parser_foo = subparsers.add_parser('foo')
      >>> parser_foo.add_argument('-x', type=int, default=1)
      >>> parser_foo.add_argument('y', type=float)
      >>> parser_foo.set_defaults(func=foo)
      >>>
      >>> # 创建针对 "bar" 命令的解析器
      >>> parser_bar = subparsers.add_parser('bar')
      >>> parser_bar.add_argument('z')
      >>> parser_bar.set_defaults(func=bar)
      >>>
      >>> # 解析参数并调用被选定的任何函数
      >>> args = parser.parse_args('foo 1 -x 2'.split())
      >>> args.func(args)
      2.0
      >>>
      >>> # 解析参数并调用被选定的任何函数
      >>> args = parser.parse_args('bar XYZYX'.split())
      >>> args.func(args)
      ((XYZYX))

  通过这种方式，你可以在参数解析结束后让 `parse_args()` 执行调用适当函数的任务。 像这样将函数关联到动作通常是你处理每个子解析器的不同动作的最简便方式。 但是，如果有必要检查被唤起的子解析器的名称，则 `add_subparsers()` 调用的 `dest` 关键字参数将可实现:

      >>> parser = argparse.ArgumentParser()
      >>> subparsers = parser.add_subparsers(dest='subparser_name')
      >>> subparser1 = subparsers.add_parser('1')
      >>> subparser1.add_argument('-x')
      >>> subparser2 = subparsers.add_parser('2')
      >>> subparser2.add_argument('y')
      >>> parser.parse_args(['2', 'frobble'])
      Namespace(subparser_name='2', y='frobble')

  在 3.7 版本发生变更: 新增 required 仅限关键字形参。

### FileType 对象

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

  `FileType` 工厂类用于创建可作为 `ArgumentParser.add_argument()` 的 type 参数传入的对象。 以 `FileType` 对象作为其类型的参数将使用命令行参数以所请求模式、缓冲区大小、编码格式和错误处理方式打开文件（请参阅 `open()` 函数了解详情）:

      >>> parser = argparse.ArgumentParser()
      >>> parser.add_argument('--raw', type=argparse.FileType('wb', 0))
      >>> parser.add_argument('out', type=argparse.FileType('w', encoding='UTF-8'))
      >>> 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'>)

  FileType 对象能理解伪参数 `'-'` 并会自动将其转换为 `sys.stdin` 用于可读的 `FileType` 对象以及 `sys.stdout` 用于可写的 `FileType` 对象:

      >>> parser = argparse.ArgumentParser()
      >>> parser.add_argument('infile', type=argparse.FileType('r'))
      >>> parser.parse_args(['-'])
      Namespace(infile=<_io.TextIOWrapper name='<stdin>' encoding='UTF-8'>)

  在 3.4 版本发生变更: 增加了 encodings 和 errors 形参。

### 参数组

ArgumentParser.add_argument_group(title=None, description=None, *[, argument_default][, conflict_handler])

  在默认情况下，`ArgumentParser` 会在显示帮助消息时将命令行参数分为“位置参数”和“选项”两组。 当存在比默认更好的分组概念时，可以使用 `add_argument_group()` 方法来创建适当的分组:

      >>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)
      >>> group = parser.add_argument_group('group')
      >>> group.add_argument('--foo', help='foo help')
      >>> group.add_argument('bar', help='bar help')
      >>> parser.print_help()
      usage: PROG [--foo FOO] bar

      group:
        bar    bar help
        --foo FOO  foo help

  `add_argument_group()` 方法返回一个具有 `add_argument()` 方法的参数分组对象，这与常规的 `ArgumentParser` 一样。 当一个参数被加入分组时，解析器儒将地它视为一个正常的参数，但是会在单独的帮助消息分组中显示该参数。 `add_argument_group()` 方法接受 title 和 description 参数以使用它们来定制显示内容:

      >>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)
      >>> group1 = parser.add_argument_group('group1', 'group1 description')
      >>> group1.add_argument('foo', help='foo help')
      >>> group2 = parser.add_argument_group('group2', 'group2 description')
      >>> group2.add_argument('--bar', help='bar help')
      >>> parser.print_help()
      usage: PROG [--bar BAR] foo

      group1:
        group1 description

        foo    foo help

      group2:
        group2 description

        --bar BAR  bar help

  可选的仅限关键字形参 argument_default 和 conflict_handler 允许对参数分组行为进行更细粒度的控制。 这些形参具有与 `ArgumentParser` 构造器中相同的含义，但是专门应用于参数分组而不是整个解析器。

  请注意任意不在你的自定义分组中的参数最终都将回到通常的“位置参数”和“可选参数”分组中。

  在 3.11 版本发生变更: 在参数分组上调用 `add_argument_group()` 已被弃用。 此特性从未受到支持并且不保证总能正确工作。此函数出现在 API 中是继承导致的意外并将在未来被移除。

### 互斥

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')
      >>> group.add_argument('--bar', action='store_false')
      >>> 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 参数，表示在互斥组中至少有一个参数是需要的:

      >>> parser = argparse.ArgumentParser(prog='PROG')
      >>> group = parser.add_mutually_exclusive_group(required=True)
      >>> group.add_argument('--foo', action='store_true')
      >>> group.add_argument('--bar', action='store_false')
      >>> parser.parse_args([])
      usage: PROG [-h] (--foo | --bar)
      PROG: error: one of the arguments --foo --bar is required

  请注意当前互斥的参数组不支持 `add_argument_group()` 的 title 和 description 参数。 但是，互斥的参数数可以被添加到具有 title 和 description 的参数组中。 例如:

      >>> parser = argparse.ArgumentParser(prog='PROG')
      >>> group = parser.add_argument_group('Group title', 'Group description')
      >>> exclusive_group = group.add_mutually_exclusive_group(required=True)
      >>> exclusive_group.add_argument('--foo', help='foo help')
      >>> exclusive_group.add_argument('--bar', help='bar help')
      >>> parser.print_help()
      usage: PROG [-h] (--foo FOO | --bar BAR)

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

      Group title:
        Group description

        --foo FOO   foo help
        --bar BAR   bar help

  在 3.11 版本发生变更: 在互斥的分组上调用 `add_argument_group()` 或 `add_mutually_exclusive_group()` 已被弃用。 这些特性从未受到支持并且不保证总能正确工作。 这些函数出现在 API 中是继承导致的意外并将在未来被移除。

### 解析器默认值

ArgumentParser.set_defaults(**kwargs)

  在大多数时候，`parse_args()` 所返回对象的属性将完全通过检查命令行参数和参数动作来确定。 `set_defaults()` 则允许加入一些无须任何命令行检查的额外属性:

      >>> parser = argparse.ArgumentParser()
      >>> parser.add_argument('foo', type=int)
      >>> parser.set_defaults(bar=42, baz='badger')
      >>> parser.parse_args(['736'])
      Namespace(bar=42, baz='badger', foo=736)

  请注意解析器层级的默认值总是会覆盖参数层级的默认值:

      >>> parser = argparse.ArgumentParser()
      >>> parser.add_argument('--foo', default='bar')
      >>> parser.set_defaults(foo='spam')
      >>> parser.parse_args([])
      Namespace(foo='spam')

  解析器层级默认值在需要多解析器时会特别有用。 请参阅 `add_subparsers()` 方法了解此类型的一个示例。

ArgumentParser.get_default(dest)

  获取一个命名空间属性的默认值，该值是由 `add_argument()` 或 `set_defaults()` 设置的:

      >>> parser = argparse.ArgumentParser()
      >>> parser.add_argument('--foo', default='badger')
      >>> parser.get_default('foo')
      'badger'

### 打印帮助

在大多数典型应用中，`parse_args()` 将负责任何用法和错误消息的格式化和打印。 但是，也可使用某些其他格式化方法:

ArgumentParser.print_usage(file=None)

  打印一段简短描述，说明应当如何在命令行中唤起 `ArgumentParser`。 如果 file 为 `None`，则默认使用 `sys.stdout`。

ArgumentParser.print_help(file=None)

  打印一条帮助消息，包括程序用法和通过 `ArgumentParser` 注册的相关参数信息。 如果 file 为 `None`，则默认使用 `sys.stdout`。

还存在这些方法的几个变化形式，它们只返回字符串而不打印消息:

ArgumentParser.format_usage()

  返回一个包含简短描述的字符串，说明应当如何在命令行中唤起 `ArgumentParser`。

ArgumentParser.format_help()

  反回一个包含帮助消息的字符串，包括程序用法和通过 `ArgumentParser` 注册的相关参数信息。

### 部分解析

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

  有时一个脚本只需要处理特定的命令行参数集合，把不能识别的参数留给其他脚本或程序。 在这种情况下，`parse_known_args()` 方法就会很有用处。

  此方法的运作方式与 `parse_args()` 类似，但它不会针对额外的不能识别的参数引发错误。 它会解析已知参数并返回一个包含已填充命名空间和不能识别的参数列表的二元组。

      >>> parser = argparse.ArgumentParser()
      >>> parser.add_argument('--foo', action='store_true')
      >>> parser.add_argument('bar')
      >>> parser.parse_known_args(['--foo', '--badger', 'BAR', 'spam'])
      (Namespace(bar='BAR', foo=True), ['--badger', 'spam'])

警告

前缀匹配 规则应用于 `parse_known_args()`。 一个解析器即使在某个选项只是已知选项的前缀时也能读取该选项，而不是将其放入剩余参数列表。

### 自定义文件解析

ArgumentParser.convert_arg_line_to_args(arg_line)

  从文件读取的参数（见 `ArgumentParser` 的 fromfile_prefix_chars 关键字参数）将是一行读取一个参数。 `convert_arg_line_to_args()` 可被重写以使用更复杂的读取方式。

  此方法接受从参数文件读取的字符串形式的单个参数 arg_line。 它返回从该字符串解析出的参数列表。 此方法将在每次按顺序从参数文件读取一行时被调用一次。

  此方法的一个有用的重写是将每个以空格分隔的单词视为一个参数。 下面的例子演示了如何实现这一点:

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

### 退出方法

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

  此方法将终结程序，退出时附带指定的 status，并且如果给出了 message 则会在退出前将其打印到 `sys.stderr`。 用户可重写此方法以不同方式来处理这些步骤:

      class ErrorCatchingArgumentParser(argparse.ArgumentParser):
          def exit(self, status=0, message=None):
              if status:
                  raise Exception(f'Exiting because of an error: {message}')
              exit(status)

ArgumentParser.error(message)

  此方法将把用法消息包括 message 打印到 `sys.stderr` 并附带状态码 2 终结程序。

### 混合解析

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

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

  许多 Unix 命令允许用户混用可选参数与位置参数。 `parse_intermixed_args()` 和 `parse_known_intermixed_args()` 方法均支持这种解析风格。

  这些解析器并不支持所有的 `argparse` 特性，并且当不受支持的特性被使用时将会引发异常。 具体来说，子解析器以及同时包括可选参数和位置参数的互斥分组是不受支持的。

  下面的例子显示了 `parse_known_args()` 与 `parse_intermixed_args()` 之间的差异：前者会将 `['2', '3']` 返回为未解析的参数，而后者会将所有位置参数收集至 `rest` 中。

      >>> parser = argparse.ArgumentParser()
      >>> parser.add_argument('--foo')
      >>> parser.add_argument('cmd')
      >>> parser.add_argument('rest', nargs='*', type=int)
      >>> parser.parse_known_args('doit 1 --foo bar 2 3'.split())
      (Namespace(cmd='doit', foo='bar', rest=[1]), ['2', '3'])
      >>> parser.parse_intermixed_args('doit 1 --foo bar 2 3'.split())
      Namespace(cmd='doit', foo='bar', rest=[1, 2, 3])

  `parse_known_intermixed_args()` 返回由两个条目组成的元组，其中包含带成员的命名空间以及剩余参数字符串列表。 当存在任何剩余的未解析参数字符串时 `parse_intermixed_args()` 将引发一个错误。

  Added in version 3.7.

### 注册自定义的类型或动作

ArgumentParser.register(registry_name, value, object)

  在某些时候有必要在错误消息中使用自定义的字符串以提供对用户更友好的输出。 在这种情况下，可以使用 `register()` 来注册带有解析器的自定义动作或类型并允许你按其注册名称而非其可调用对象名称来引用该类型。

  `register()` 方法接受三个参数 —— registry_name，指定将要存储对象的内部注册表 (例如 `action`, `type`)，value，将要注册对象对应的键，以及 object，将要注册的可调用对象。

  下面的例子演示了如何注册一个带解析器的自定义类型:

      >>> import argparse
      >>> parser = argparse.ArgumentParser()
      >>> parser.register('type', 'hexadecimal integer', lambda s: int(s, 16))
      >>> parser.add_argument('--foo', type='hexadecimal integer')
      _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type='hexadecimal integer', choices=None, required=False, help=None, metavar=None, deprecated=False)
      >>> parser.parse_args(['--foo', '0xFA'])
      Namespace(foo=250)
      >>> parser.parse_args(['--foo', '1.2'])
      usage: PROG [-h] [--foo FOO]
      PROG: error: argument --foo: invalid 'hexadecimal integer' value: '1.2'

## 异常

exception argparse.ArgumentError

  来自创建或使用某个参数的消息（可选或位置参数）。

  此异常的字符串值即异常消息，并附带有导致该异常的参数的相关信息。

exception argparse.ArgumentTypeError

  当从一个命令行字符串到特定类型的转换出现问题时引发。

指南与教程

- argparse 教程
- 将 `optparse` 代码迁移至 `argparse`