"getopt" --- C 风格的命令行选项解析器
*************************************

**源代码:** Lib/getopt.py

备注:

  该模块被认为具有完备的特性。 在 "optparse" 模块中提供了一个针对此
  API 的更为声明式和可扩展的替代物。 对命令行形参处理进一步的功能增强
  或是作为 PyPI 上的第三方模块，或是作为 "argparse" 模块中的特性被提供
  。

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

此模块可协助脚本解析 "sys.argv" 中的命令行参数。 它支持与 Unix
"getopt()" 函数相同的惯例 (包括形式为 '"-"' 和 '"--"' 的参数的特殊含义
)。 也可以通过可选的第三个参数来使用类似于 GNU 软件所支持形式的长选项
。

不熟悉 Unix "getopt()" 函数的用户应当考虑改用 "argparse" 模块。 熟悉
Unix "getopt()" 函数，但希望在获得等价的行为同时使用更少的代码又具有更
好的帮助和错误信息的用户应当考虑使用 "optparse" 模块。 请参阅 选择参数
解析库 了解更多细节。

此模块提供了两个函数和一个异常:

getopt.getopt(args, shortopts, longopts=[])

   解析命令行选项与形参列表。 *args* 是要解析的参数列表，不包含最开头
   的对正在运行的程序的引用。 通常，这意味着 "sys.argv[1:]"。
   *shortopts* 是脚本要识别的选项字母字符串，选项需要一个参数则后跟一
   个冒号（"':'"），选项接受一个可选参数则后跟两个冒号（"'::'"）；即与
   Unix "getopt()" 所用的格式相同。

   备注:

     与 GNU "getopt()" 不同，在非选项参数之后，所有后续参数都会被视为
     非选项。 这类似于非 GNU Unix 系统的运作方式。

   如果指定了 *longopts*，则必须为一个由应当被支持的长选项名称组成的列
   表。 开头的 "'--'" 字符不应被包括在选项名称中。 需要参数的长选项应
   当后跟一个等号 ("'='")。 接受可选参数的长选项应当后跟等号和问号（
   "'=?'"）。 如果想仅接受长选项，则 *shortopts* 应为一个空字符串。 命
   令行中的长选项只要提供了恰好能匹配可接受选项之一的选项名称前缀即可
   被识别。 举例来说，如果 *longopts* 为 "['foo', 'frob']"，则选项 "--
   fo" 将匹配为 "--foo"，但 "--f" 将不能得到唯一匹配，因此将引发
   "GetoptError"。

   返回值由两个元素组成：第一个是 "(option, value)" 对的列表；第二个是
   在去除该选项列表后余下的程序参数列表（这也就是 *args* 的尾部切片）
   。每个被返回的选项与值对的第一个元素是选项，短选项前缀一个连字符 (
   例如 "'-x'")，长选项则前缀两个连字符 (例如 "'--long-option'")，第二
   个元素是选项参数，如果选项不带参数则为空字符串。 列表中选项的排列顺
   序与它们被解析的顺序相同，因此允许多次出现。 长选项与短选项可以混用
   。

   在 3.14 版本发生变更: 支持可选参数。

getopt.gnu_getopt(args, shortopts, longopts=[])

   此函数与 "getopt()" 类似，区别在于它默认使用 GNU 风格的扫描模式。
   这意味着选项和非选项参数可能会混在一起。 "getopt()" 函数将在遇到非
   选项参数时立即停止处理选项。

   如果选项字符串的第一个字符为 "'+'"，或者如果设置了环境变量
   "POSIXLY_CORRECT"，则选项处理会在遇到非选项参数时立即停止。

   如果选项字符串的第一个字符是 "'-'"，则后面跟着选项的非选项参数将作
   为一对添加到选项和值对列表中，该对的第一个元素是 "None"，第二个元素
   是非选项参数列表。"gnu_getopt()" 结果的第二个元素是最后一个选项后的
   程序参数列表。

   在 3.14 版本发生变更: 支持按顺序返回混合了的选项和非选项参数。

exception getopt.GetoptError

   当参数列表中出现不可识别的选项或当一个需要参数的选项未带参数时将引
   发此异常。 此异常的参数是一个指明错误原因的字符串。 对于长选项，将
   一个参数传给不需要参数的选项也将导致此异常被引发。 "msg" 和 "opt"
   属性将给出错误消息和关联的选项；如果没有关联到此异常的特定选项，则
   "opt" 将为空字符串。

exception getopt.error

   "GetoptError" 的别名；用于向后兼容。

一个仅使用 Unix 风格选项的例子:

   >>> import getopt
   >>> args = '-a -b -cfoo -d bar a1 a2'.split()
   >>> args
   ['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2']
   >>> optlist, args = getopt.getopt(args, 'abc:d:')
   >>> optlist
   [('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')]
   >>> args
   ['a1', 'a2']

使用长选项名也同样容易:

   >>> s = '--condition=foo --testing --output-file abc.def -x a1 a2'
   >>> args = s.split()
   >>> args
   ['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2']
   >>> optlist, args = getopt.getopt(args, 'x', [
   ...     'condition=', 'output-file=', 'testing'])
   >>> optlist
   [('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')]
   >>> args
   ['a1', 'a2']

应当显式地指定可选参数：

   >>> s = '-Con -C --color=off --color a1 a2'
   >>> args = s.split()
   >>> args
   ['-Con', '-C', '--color=off', '--color', 'a1', 'a2']
   >>> optlist, args = getopt.getopt(args, 'C::', ['color=?'])
   >>> optlist
   [('-C', 'on'), ('-C', ''), ('--color', 'off'), ('--color', '')]
   >>> args
   ['a1', 'a2']

选项和非选项参数的顺序可以被保留：

   >>> s = 'a1 -x a2 a3 a4 --long a5 a6'
   >>> args = s.split()
   >>> args
   ['a1', '-x', 'a2', 'a3', 'a4', '--long', 'a5', 'a6']
   >>> optlist, args = getopt.gnu_getopt(args, '-x:', ['long='])
   >>> optlist
   [(None, ['a1']), ('-x', 'a2'), (None, ['a3', 'a4']), ('--long', 'a5')]
   >>> args
   ['a6']

在脚本中，典型的用法是这样的:

   import getopt, sys

   def main():
       try:
           opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
       except getopt.GetoptError as err:
           # 打印帮助信息并退出。
           print(err)  # 将打印 "option -a not recognized" 之类的消息
           usage()
           sys.exit(2)
       output = None
       verbose = False
       for o, a in opts:
           if o == "-v":
               verbose = True
           elif o in ("-h", "--help"):
               usage()
               sys.exit()
           elif o in ("-o", "--output"):
               output = a
           else:
               assert False, "unhandled option"
       process(args, output=output, verbose=verbose)

   if __name__ == "__main__":
       main()

请注意可以通过使用 "optparse" 模块以更少的代码并附带更清晰的帮助和错误
消息生成等价的命令行界面：

   import optparse

   if __name__ == '__main__':
       parser = optparse.OptionParser()
       parser.add_option('-o', '--output')
       parser.add_option('-v', dest='verbose', action='store_true')
       opts, args = parser.parse_args()
       process(args, output=opts.output, verbose=opts.verbose)

对这种情况也可以通过使用 "argparse" 模块来生成大致等价的命令行界面：

   import argparse

   if __name__ == '__main__':
       parser = argparse.ArgumentParser()
       parser.add_argument('-o', '--output')
       parser.add_argument('-v', dest='verbose', action='store_true')
       parser.add_argument('rest', nargs='*')
       args = parser.parse_args()
       process(args.rest, output=args.output, verbose=args.verbose)

请参阅 选择参数解析库 了解有关此代码的 "argparse" 版本与 "optparse" (
和 "getopt") 版本间行为差异的详情。

参见:

  模块 "optparse"
     声明式命令行选项解析。

  模块 "argparse"
     更有针对性的命令行选项和参数解析库。
