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

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