"argparse" --- 命令行选项、参数和子命令解析器
*********************************************

3.2 新版功能.

**源代码：** Lib/argparse.py

======================================================================


教程
^^^^

此页面包含该 API 的参考信息。有关 Python 命令行解析更细致的介绍，请参
阅 argparse 教程。

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


示例
====

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

   import argparse

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

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

假设上面的 Python 代码保存在名为 "prog.py" 的文件中，它可以在命令行运
行并提供有用的帮助消息：

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

   Process some integers.

   positional arguments:
    N           an integer for the accumulator

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

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

   $ python prog.py 1 2 3 4
   4

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

如果传入无效参数，则会报出错误：

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

以下部分将引导你完成这个示例。


创建一个解析器
--------------

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

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

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


添加参数
--------

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

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

稍后，调用 "parse_args()" 将返回一个具有 "integers" 和 "accumulate" 两
个属性的对象。"integers" 属性将是一个包含一个或多个整数的列表，而
"accumulate" 属性当命令行中指定了 "--sum" 参数时将是 "sum()" 函数，否
则则是 "max()" 函数。


解析参数
--------

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

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

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


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 - 程序的名称（默认："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 - Determines whether or not ArgumentParser exits
     with error info when an error occurs. (default: "True")

   在 3.5 版更改: 添加 *allow_abbrev* 参数。

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

   在 3.9 版更改: *exit_on_error* parameter was added.

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


prog
----

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

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

该程序的帮助信息将显示 "myprogram.py" 作为程序名称（无论程序从何处被调
用）：

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

   optional arguments:
    -h, --help  show this help message and exit
    --foo FOO   foo help
   $ cd ..
   $ python subdir/myprogram.py --help
   usage: myprogram.py [-h] [--foo FOO]

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

要更改这样的默认行为，可以使用 "prog=" 参数为 "ArgumentParser" 提供另
一个值：

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

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

需要注意的是，无论是从 "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]

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


usage
-----

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

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

   positional arguments:
    bar          bar help

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

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

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

   positional arguments:
    bar          bar help

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

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


description
-----------

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

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

   A foo that bars

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

在默认情况下，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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   positional arguments:
     float

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


prefix_chars
------------

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

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

The "prefix_chars=" 参数默认使用 "'-'". 支持一系列字符，但是不包括 "-"
，这样会产生不被允许的 "-f/--foo" 选项。


fromfile_prefix_chars
---------------------

有些时候，先举个例子，当处理一个特别长的参数列表的时候，把它存入一个文
件中而不是在命令行打出来会很有意义。如果 "fromfile_prefix_chars=" 参数
提供给 "ArgumentParser" 构造函数，之后所有类型的字符的参数都会被当成文
件处理，并且会被文件包含的参数替代。举个栗子:

   >>> with open('args.txt', 'w') as fp:
   ...     fp.write('-f\nbar')
   >>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
   >>> parser.add_argument('-f')
   >>> parser.parse_args(['-f', 'foo', '@args.txt'])
   Namespace(f='bar')

从文件读取的参数在默认情况下必须一个一行（但是可参见
"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":

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

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]

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

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


add_help
--------

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

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

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

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

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

有时候可能会需要关闭额外的帮助信息。这可以通过在 "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]

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

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


exit_on_error
-------------

Normally, when you pass an invalid argument list to the "parse_args()"
method of an "ArgumentParser", it will exit with error info.

If the user would like catch errors manually, the feature can be
enable by setting "exit_on_error" to "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

3.9 新版功能.


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 或者是一个简单的参数名。例如，可以选项可以被这样创
建:

   >>> 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'" - 存储参数的值。这是默认的动作。例如:

     >>> parser = argparse.ArgumentParser()
     >>> parser.add_argument('--foo')
     >>> parser.parse_args('--foo 1'.split())
     Namespace(foo='1')

* "'store_const'" - 存储被 const 命名参数指定的值。 "'store_const'" 动
  作通常用在选项中来指定一些标志。例如:

     >>> 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'" 分别用作
  存储 "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'>])

* "'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

* "'extend'" - 这会存储一个列表，并将每个参数值加入到列表中。 示例用法
  :

     >>> 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 新版功能.

You may also specify an arbitrary action by passing an Action subclass
or other object that implements the same interface. The
"BooleanOptionalAction" is available in "argparse" and adds support
for boolean actions such as "--foo" and "--no-foo":

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

The recommended way to create a custom action is to extend "Action",
overriding the "__call__" method and optionally the "__init__" and
"format_usage" methods.

一个自定义动作的例子:

   >>> class FooAction(argparse.Action):
   ...     def __init__(self, option_strings, dest, nargs=None, **kwargs):
   ...         if nargs is not None:
   ...             raise ValueError("nargs not allowed")
   ...         super(FooAction, self).__init__(option_strings, dest, **kwargs)
   ...     def __call__(self, parser, namespace, values, option_string=None):
   ...         print('%r %r %r' % (namespace, values, option_string))
   ...         setattr(namespace, self.dest, values)
   ...
   >>> parser = argparse.ArgumentParser()
   >>> parser.add_argument('--foo', action=FooAction)
   >>> 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

* "argarse.REMAINDER"。所有剩余的命令行参数被聚集到一个列表中。这通常
  在从一个命令行功能传递参数到另一个命令行功能中时有用:

     >>> parser = 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" 值在选项未在命令行中出现时使用:

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

如果 "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)

提供 "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
----

默认情况下，"ArgumentParser" 对象将命令行参数当作简单字符串读入。然而
，命令行字符串经常需要被当作其它的类型，比如 "float" 或者 "int"。
"add_argument()" 的 "type" 关键词参数允许任何的类型检查和类型转换。一
般的内建类型和函数可以直接被 "type" 参数使用。

   >>> parser = argparse.ArgumentParser()
   >>> parser.add_argument('foo', type=int)
   >>> parser.add_argument('bar', type=open)
   >>> parser.parse_args('2 temp.txt'.split())
   Namespace(bar=<_io.TextIOWrapper name='temp.txt' encoding='UTF-8'>, foo=2)

当 "type" 参数被应用到默认参数时，请参考 default 参数的部分。

为方便使用不同类型的文件，argparse 模块提供了 FileType 工厂类，该类接
受 "mode=", "bufsize=", "encoding=" 和 "errors=" 等 "open()" 函数参数
。 例如，"FileType('w')" 可被用来创建一个可写文件:

   >>> parser = argparse.ArgumentParser()
   >>> parser.add_argument('bar', type=argparse.FileType('w'))
   >>> parser.parse_args(['out.txt'])
   Namespace(bar=<_io.TextIOWrapper name='out.txt' encoding='UTF-8'>)

"type=" 可接受任意可调用对象，该对象应传入单个字符串参数并返回转换后的
值:

   >>> def perfect_square(string):
   ...     value = int(string)
   ...     sqrt = math.sqrt(value)
   ...     if sqrt != int(sqrt):
   ...         msg = "%r is not a perfect square" % string
   ...         raise argparse.ArgumentTypeError(msg)
   ...     return value
   ...
   >>> parser = argparse.ArgumentParser(prog='PROG')
   >>> parser.add_argument('foo', type=perfect_square)
   >>> parser.parse_args(['9'])
   Namespace(foo=9)
   >>> parser.parse_args(['7'])
   usage: PROG [-h] foo
   PROG: error: argument foo: '7' is not a perfect square

choices 关键词参数可能会使类型检查者更方便的检查一个范围的值。

   >>> parser = argparse.ArgumentParser(prog='PROG')
   >>> parser.add_argument('foo', type=int, choices=range(5, 10))
   >>> parser.parse_args(['7'])
   Namespace(foo=7)
   >>> parser.parse_args(['11'])
   usage: PROG [-h] {5,6,7,8,9}
   PROG: error: argument foo: invalid choice: 11 (choose from 5, 6, 7, 8, 9)

详情请查阅 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 相匹配:

   >>> 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" 对象，"set" 对象以及自
定义容器都是受支持的。


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: argparse.py [-h] [--foo FOO]
   argparse.py: error: option --foo is required

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

注解:

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


help
----

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

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

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

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

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

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


metavar
-------

当 "ArgumentParser" 生成帮助消息时，它需要用某种方式来引用每个预期的参
数。 默认情况下，ArgumentParser 对象使用 dest 值作为每个对象的 "name"
。 默认情况下，对于位置参数动作，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

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

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

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

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

   >>> parser = argparse.ArgumentParser(prog='PROG')
   >>> parser.add_argument('-x', nargs=2)
   >>> parser.add_argument('--foo', nargs=2, metavar=('bar', 'baz'))
   >>> parser.print_help()
   usage: PROG [-h] [-x X X] [--foo bar baz]

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


dest
----

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

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

For optional argument actions, the value of "dest" is normally
inferred from the option strings.  "ArgumentParser" generates the
value of "dest" by taking the first long option string and stripping
away the initial "--" string.  If no long option strings were
supplied, "dest" will be derived from the first short option string by
stripping the initial "-" character.  Any internal "-" characters will
be converted to "_" characters to make sure the string is a valid
attribute name.  The examples below illustrate this behavior:

   >>> 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" allows a custom attribute name to be provided:

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


Action classes
--------------

Action classes implement the Action API, a callable which returns a
callable which processes arguments from the command-line. Any object
which follows this API may be passed as the "action" parameter to
"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 objects are used by an ArgumentParser to represent the
information needed to parse a single argument from one or more strings
from the command line. The Action class must accept the two positional
arguments plus any keyword arguments passed to
"ArgumentParser.add_argument()" except for the "action" itself.

Instances of Action (or return value of any callable to the "action"
parameter) should have attributes "dest", "option_strings", "default",
"type", "required", "help", etc. defined. The easiest way to ensure
these attributes are defined is to call "Action.__init__".

Action instances should be callable, so subclasses must override the
"__call__" method, which should accept four parameters:

* "parser" - The ArgumentParser object which contains this action.

* "namespace" - The "Namespace" object that will be returned by
  "parse_args()".  Most actions add an attribute to this object using
  "setattr()".

* "values" - The associated command-line arguments, with any type
  conversions applied.  Type conversions are specified with the type
  keyword argument to "add_argument()".

* "option_string" - The option string that was used to invoke this
  action. The "option_string" argument is optional, and will be absent
  if the action is associated with a positional argument.

The "__call__" method may perform arbitrary actions, but will
typically set attributes on the "namespace" based on "dest" and
"values".

Action subclasses can define a "format_usage" method that takes no
argument and return a string which will be used when printing the
usage of the program. If such method is not provided, a sensible
default will be used.


parse_args() 方法
=================

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

   Convert argument strings to objects and assign them as attributes
   of the namespace.  Return the populated namespace.

   Previous calls to "add_argument()" determine exactly what objects
   are created and how they are assigned. See the documentation for
   "add_argument()" for details.

   * args - List of strings to parse.  The default is taken from
     "sys.argv".

   * namespace - An object to take the attributes.  The default is a
     new empty "Namespace" object.


Option value syntax
-------------------

The "parse_args()" method supports several ways of specifying the
value of an option (if it takes one).  In the simplest case, the
option and its value are passed as two separate arguments:

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

For long options (options with names longer than a single character),
the option and value can also be passed as a single command-line
argument, using "=" to separate them:

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

For short options (options only one character long), the option and
its value can be concatenated:

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

Several short options can be joined together, using only a single "-"
prefix, as long as only the last option (or none of them) requires a
value:

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


无效的参数
----------

While parsing the command line, "parse_args()" checks for a variety of
errors, including ambiguous options, invalid types, invalid options,
wrong number of positional arguments, etc.  When it encounters such an
error, it exits and prints the error along with a usage message:

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


包含 "-" 的参数
---------------

The "parse_args()" method attempts to give errors whenever the user
has clearly made a mistake, but some situations are inherently
ambiguous.  For example, the command-line argument "-1" could either
be an attempt to specify an option or an attempt to provide a
positional argument. The "parse_args()" method is cautious here:
positional arguments may only begin with "-" if they look like
negative numbers and there are no options in the parser that look like
negative numbers:

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

If you have positional arguments that must begin with "-" and don't
look like negative numbers, you can insert the pseudo-argument "'--'"
which tells "parse_args()" that everything after that is a positional
argument:

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


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

The "parse_args()" method by default allows long options to be
abbreviated to a prefix, if the abbreviation is unambiguous (the
prefix matches a unique option):

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

An error is produced for arguments that could produce more than one
options. This feature can be disabled by setting allow_abbrev to
"False".


Beyond "sys.argv"
-----------------

Sometimes it may be useful to have an ArgumentParser parse arguments
other than those of "sys.argv".  This can be accomplished by passing a
list of strings to "parse_args()".  This is useful for testing at the
interactive prompt:

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

   Simple class used by default by "parse_args()" to create an object
   holding attributes and return it.

This class is deliberately simple, just an "object" subclass with a
readable string representation. If you prefer to have dict-like view
of the attributes, you can use the standard Python idiom, "vars()":

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

It may also be useful to have an "ArgumentParser" assign attributes to
an already existing object, rather than a new "Namespace" object.
This can be achieved by specifying the "namespace=" keyword argument:

   >>> 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][, option_string][, dest][, required][, help][, metavar])

   Many programs split up their functionality into a number of sub-
   commands, for example, the "svn" program can invoke sub-commands
   like "svn checkout", "svn update", and "svn commit".  Splitting up
   functionality this way can be a particularly good idea when a
   program performs several different functions which require
   different kinds of command-line arguments. "ArgumentParser"
   supports the creation of such sub-commands with the
   "add_subparsers()" method.  The "add_subparsers()" method is
   normally called with no arguments and returns a special action
   object.  This object has a single method, "add_parser()", which
   takes a command name and any "ArgumentParser" constructor
   arguments, and returns an "ArgumentParser" object that can be
   modified as usual.

   形参的描述

   * title - title for the sub-parser group in help output; by default
     "subcommands" if description is provided, otherwise uses title
     for positional arguments

   * description - description for the sub-parser group in help
     output, by default "None"

   * prog - usage information that will be displayed with sub-command
     help, by default the name of the program and any positional
     arguments before the subparser argument

   * parser_class - class which will be used to create sub-parser
     instances, by default the class of the current parser (e.g.
     ArgumentParser)

   * action - the basic type of action to be taken when this argument
     is encountered at the command line

   * dest - name of the attribute under which sub-command name will be
     stored; by default "None" and no value is stored

   * required - Whether or not a subcommand must be provided, by
     default "False" (added in 3.7)

   * help - help for sub-parser group in help output, by default
     "None"

   * metavar - string presenting available sub-commands in help; by
     default it is "None" and presents sub-commands in form {cmd1,
     cmd2, ..}

   一些使用示例:

      >>> # create the top-level parser
      >>> parser = argparse.ArgumentParser(prog='PROG')
      >>> parser.add_argument('--foo', action='store_true', help='foo help')
      >>> subparsers = parser.add_subparsers(help='sub-command help')
      >>>
      >>> # create the parser for the "a" command
      >>> parser_a = subparsers.add_parser('a', help='a help')
      >>> parser_a.add_argument('bar', type=int, help='bar help')
      >>>
      >>> # create the parser for the "b" command
      >>> parser_b = subparsers.add_parser('b', help='b help')
      >>> parser_b.add_argument('--baz', choices='XYZ', help='baz help')
      >>>
      >>> # parse some argument lists
      >>> parser.parse_args(['a', '12'])
      Namespace(bar=12, foo=False)
      >>> parser.parse_args(['--foo', 'b', '--baz', 'Z'])
      Namespace(baz='Z', foo=True)

   Note that the object returned by "parse_args()" will only contain
   attributes for the main parser and the subparser that was selected
   by the command line (and not any other subparsers).  So in the
   example above, when the "a" command is specified, only the "foo"
   and "bar" attributes are present, and when the "b" command is
   specified, only the "foo" and "baz" attributes are present.

   Similarly, when a help message is requested from a subparser, only
   the help for that particular parser will be printed.  The help
   message will not include parent parser or sibling parser messages.
   (A help message for each subparser command, however, can be given
   by supplying the "help=" argument to "add_parser()" as above.)

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

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

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

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

      positional arguments:
        bar     bar help

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

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

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

   The "add_subparsers()" method also supports "title" and
   "description" keyword arguments.  When either is present, the
   subparser's commands will appear in their own group in the help
   output.  For example:

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

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

      subcommands:
        valid subcommands

        {foo,bar}   additional help

   Furthermore, "add_parser" supports an additional "aliases"
   argument, which allows multiple strings to refer to the same
   subparser. This example, like "svn", aliases "co" as a shorthand
   for "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')

   One particularly effective way of handling sub-commands is to
   combine the use of the "add_subparsers()" method with calls to
   "set_defaults()" so that each subparser knows which Python function
   it should execute.  For example:

      >>> # sub-command functions
      >>> def foo(args):
      ...     print(args.x * args.y)
      ...
      >>> def bar(args):
      ...     print('((%s))' % args.z)
      ...
      >>> # create the top-level parser
      >>> parser = argparse.ArgumentParser()
      >>> subparsers = parser.add_subparsers()
      >>>
      >>> # create the parser for the "foo" command
      >>> 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)
      >>>
      >>> # create the parser for the "bar" command
      >>> parser_bar = subparsers.add_parser('bar')
      >>> parser_bar.add_argument('z')
      >>> parser_bar.set_defaults(func=bar)
      >>>
      >>> # parse the args and call whatever function was selected
      >>> args = parser.parse_args('foo 1 -x 2'.split())
      >>> args.func(args)
      2.0
      >>>
      >>> # parse the args and call whatever function was selected
      >>> args = parser.parse_args('bar XYZYX'.split())
      >>> args.func(args)
      ((XYZYX))

   This way, you can let "parse_args()" do the job of calling the
   appropriate function after argument parsing is complete.
   Associating functions with actions like this is typically the
   easiest way to handle the different actions for each of your
   subparsers.  However, if it is necessary to check the name of the
   subparser that was invoked, the "dest" keyword argument to the
   "add_subparsers()" call will work:

      >>> 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 版更改: New *required* keyword argument.


FileType 对象
-------------

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

   The "FileType" factory creates objects that can be passed to the
   type argument of "ArgumentParser.add_argument()".  Arguments that
   have "FileType" objects as their type will open command-line
   arguments as files with the requested modes, buffer sizes,
   encodings and error handling (see the "open()" function for more
   details):

      >>> 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 objects understand the pseudo-argument "'-'" and
   automatically convert this into "sys.stdin" for readable "FileType"
   objects and "sys.stdout" for writable "FileType" objects:

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

   By default, "ArgumentParser" groups command-line arguments into
   "positional arguments" and "optional arguments" when displaying
   help messages. When there is a better conceptual grouping of
   arguments than this default one, appropriate groups can be created
   using the "add_argument_group()" method:

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

   The "add_argument_group()" method returns an argument group object
   which has an "add_argument()" method just like a regular
   "ArgumentParser".  When an argument is added to the group, the
   parser treats it just like a normal argument, but displays the
   argument in a separate group for help messages.  The
   "add_argument_group()" method accepts *title* and *description*
   arguments which can be used to customize this display:

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

   Note that any arguments not in your user-defined groups will end up
   back in the usual "positional arguments" and "optional arguments"
   sections.


Mutual exclusion
----------------

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* 参数。


Parser defaults
---------------

ArgumentParser.set_defaults(**kwargs)

   Most of the time, the attributes of the object returned by
   "parse_args()" will be fully determined by inspecting the command-
   line arguments and the argument actions.  "set_defaults()" allows
   some additional attributes that are determined without any
   inspection of the command line to be added:

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

   Note that parser-level defaults always override argument-level
   defaults:

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

   Parser-level defaults can be particularly useful when working with
   multiple parsers.  See the "add_subparsers()" method for an example
   of this type.

ArgumentParser.get_default(dest)

   Get the default value for a namespace attribute, as set by either
   "add_argument()" or by "set_defaults()":

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


打印帮助
--------

In most typical applications, "parse_args()" will take care of
formatting and printing any usage or error messages.  However, several
formatting methods are available:

ArgumentParser.print_usage(file=None)

   Print a brief description of how the "ArgumentParser" should be
   invoked on the command line.  If *file* is "None", "sys.stdout" is
   assumed.

ArgumentParser.print_help(file=None)

   Print a help message, including the program usage and information
   about the arguments registered with the "ArgumentParser".  If
   *file* is "None", "sys.stdout" is assumed.

There are also variants of these methods that simply return a string
instead of printing it:

ArgumentParser.format_usage()

   Return a string containing a brief description of how the
   "ArgumentParser" should be invoked on the command line.

ArgumentParser.format_help()

   Return a string containing a help message, including the program
   usage and information about the arguments registered with the
   "ArgumentParser".


Partial parsing
---------------

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

Sometimes a script may only parse a few of the command-line arguments,
passing the remaining arguments on to another script or program. In
these cases, the "parse_known_args()" method can be useful.  It works
much like "parse_args()" except that it does not produce an error when
extra arguments are present.  Instead, it returns a two item tuple
containing the populated namespace and the list of remaining argument
strings.

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

警告:

  Prefix matching rules apply to "parse_known_args()". The parser may
  consume an option even if it's just a prefix of one of its known
  options, instead of leaving it in the remaining arguments list.


自定义文件解析
--------------

ArgumentParser.convert_arg_line_to_args(arg_line)

   Arguments that are read from a file (see the
   *fromfile_prefix_chars* keyword argument to the "ArgumentParser"
   constructor) are read one argument per line.
   "convert_arg_line_to_args()" can be overridden for fancier reading.

   This method takes a single argument *arg_line* which is a string
   read from the argument file.  It returns a list of arguments parsed
   from this string. The method is called once per line read from the
   argument file, in order.

   A useful override of this method is one that treats each space-
   separated word as an argument.  The following example demonstrates
   how to do this:

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


退出方法
--------

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

   This method terminates the program, exiting with the specified
   *status* and, if given, it prints a *message* before that. The user
   can override this method to handle these steps differently:

      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)

   This method prints a usage message including the *message* to the
   standard error and terminates the program with a status code of 2.


Intermixed parsing
------------------

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

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

A number of Unix commands allow the user to intermix optional
arguments with positional arguments.  The "parse_intermixed_args()"
and "parse_known_intermixed_args()" methods support this parsing
style.

These parsers do not support all the argparse features, and will raise
exceptions if unsupported features are used.  In particular,
subparsers, "argparse.REMAINDER", and mutually exclusive groups that
include both optionals and positionals are not supported.

The following example shows the difference between
"parse_known_args()" and "parse_intermixed_args()": the former returns
"['2', '3']" as unparsed arguments, while the latter collects all the
positionals into "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()" returns a two item tuple containing
the populated namespace and the list of remaining argument strings.
"parse_intermixed_args()" raises an error if there are any remaining
unparsed argument strings.

3.7 新版功能.


升级 optparse 代码
==================

Originally, the "argparse" module had attempted to maintain
compatibility with "optparse".  However, "optparse" was difficult to
extend transparently, particularly with the changes required to
support the new "nargs=" specifiers and better usage messages.  When
most everything in "optparse" had either been copy-pasted over or
monkey-patched, it no longer seemed practical to try to maintain the
backwards compatibility.

The "argparse" module improves on the standard library "optparse"
module in a number of ways including:

* 处理位置参数。

* 支持子命令。

* Allowing alternative option prefixes like "+" and "/".

* Handling zero-or-more and one-or-more style arguments.

* Producing more informative usage messages.

* Providing a much simpler interface for custom "type" and "action".

A partial upgrade path from "optparse" to "argparse":

* Replace all "optparse.OptionParser.add_option()" calls with
  "ArgumentParser.add_argument()" calls.

* Replace "(options, args) = parser.parse_args()" with "args =
  parser.parse_args()" and add additional
  "ArgumentParser.add_argument()" calls for the positional arguments.
  Keep in mind that what was previously called "options", now in the
  "argparse" context is called "args".

* Replace "optparse.OptionParser.disable_interspersed_args()" by using
  "parse_intermixed_args()" instead of "parse_args()".

* Replace callback actions and the "callback_*" keyword arguments with
  "type" or "action" arguments.

* Replace string names for "type" keyword arguments with the
  corresponding type objects (e.g. int, float, complex, etc).

* Replace "optparse.Values" with "Namespace" and
  "optparse.OptionError" and "optparse.OptionValueError" with
  "ArgumentError".

* Replace strings with implicit arguments such as "%default" or
  "%prog" with the standard Python syntax to use dictionaries to
  format strings, that is, "%(default)s" and "%(prog)s".

* Replace the OptionParser constructor "version" argument with a call
  to "parser.add_argument('--version', action='version', version='<the
  version>')".
