optparse --- 命令行选项的解析器

源代码: Lib/optparse.py


选择参数解析库

标准库包括三个参数解析库:

  • getopt: 一个忠实地复刻过程式 C getopt API 的模块。 在最初的 Python 1.0 发布版之前就已包括在标准库中。

  • optparse: a declarative replacement for getopt that provides equivalent functionality without requiring each application to implement its own procedural option parsing logic. Included in the standard library since the Python 2.3 release.

  • argparse: 一个更有针对性的 optparse 替代物,默认提供了更多功能,代价是降低了应用程序在具体如何控制参数处理时的灵活性。 自 Python 2.7 和 Python 3.2 发布版起被包括在标准库中。

在缺少更具体的参数解析设计约束的情况下,argparse 是实现命令行应用程序的推荐选择,因为它能以最少的程用程序层级代码提供最高层级的基本功能。

getopt 被保留几乎完全是出于向下兼容性理由。 不过,它也适合在基于 getopt 的 C 应用程序中作为命令行参数处理原型搭建和测试场景中的工具。

optparse should be considered as an alternative to argparse in the following cases:

  • an application is already using optparse and doesn't want to risk the subtle behavioural changes that may arise when migrating to argparse

  • 这个应用程序需要对命令行中选项和位置形参的交错方式进行额外的控制(包括完全禁用交错特性的能力)

  • 这个应用程序需要对命令行元素进行渐进式解析的过程施加更多控制(虽然 argparse 确实支持这个功能,但实际运作的方式在某些情况下并非理想)

  • 这个应用程序需要对某些可能接受以 - 开头的参数值的命令行选项施行特殊的控制(例如程序本身调用另一个程序,而这些选项是要原样传给被调用的子程序的)

  • 这个应用程序需要其他一些 argparse 不支持,但是可利用 optparse 提供之底层接口实现的特殊的命令行参数处理行为

These considerations also mean that optparse is likely to provide a better foundation for library authors writing third party command line argument processing libraries.

以下提供一个具体的例子。请见下方两段命令行参数解析代码,其中第一段使用 optparse 实现;第二段使用 argparse 实现:

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

最明显的差异就是在 optparse 版本中,无选项参数是在选项处理完成后由应用程序单独处理的。 在 argparse 版本中,位置参数则是以与带名称的选项相同的方式声明和处理的。

不过,argparse 版本还会以与 optparse 版本不同的方式处理某些形参组合。 例如(除其他差异之外):

  • 当使用 optparse-o -v 是指定 output="-v"verbose=False,但对于 argparse 则为错误用法(将报告没有为 -o/--output 提供值,因为 -v 会被解读为代表 verbosity 旗标)

  • 类似地,当使用 optparse 时提供 -o -- 是指定 output="--"args=(),但对于 argparse 则为错误用法(同样将报告没有为 -o/--output 提供值,因为 -- 会被解读为结束选项处理并将所有剩余的值视为位置参数)

  • 当使用 optparse 时提供 -o=foo 是指定 output="=foo",但对于 argparse 则为 output="foo" (因为 = 是被作为选项形参值的替代分隔符的特例)。

这些在 argparse 版本中存在差异的行为是有必要的还是有问题的将取决于特定命令行应用程序的使用场景。

参见

click 是一个第三方参数处理库(最初是以 optparse 为基础),它允许命令行应用程序以一组被装饰的命令实现函数的方式来开发。

其他的第三方库,例如 typermsgspec-click,允许命令行界面以更有效率地集成 Python 类型标注静态检查的方式来指定。

概述

optparse is a more convenient, flexible, and powerful library for parsing command-line options than the minimalist getopt module. optparse uses a more declarative style of command-line parsing: you create an instance of OptionParser, populate it with options, and parse the command line. optparse allows users to specify options in the conventional GNU/POSIX syntax, and additionally generates usage and help messages for you.

Here's an example of using optparse in a simple script:

from optparse import OptionParser
...
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
                  help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose", default=True,
                  help="don't print status messages to stdout")

(options, args) = parser.parse_args()

通过这几行代码,你的脚本的用户可以在命令行上完成“常见任务”,例如:

<yourscript> --file=outfile -q

As it parses the command line, optparse sets attributes of the options object returned by parse_args() based on user-supplied command-line values. When parse_args() returns from parsing this command line, options.filename will be "outfile" and options.verbose will be False. optparse supports both long and short options, allows short options to be merged together, and allows options to be associated with their arguments in a variety of ways. Thus, the following command lines are all equivalent to the above example:

<yourscript> -f outfile --quiet
<yourscript> --quiet --file outfile
<yourscript> -q -foutfile
<yourscript> -qfoutfile

此外,用户还可以运行以下命令之一

<yourscript> -h
<yourscript> --help

and optparse will print out a brief summary of your script's options:

Usage: <yourscript> [options]

Options:
  -h, --help            show this help message and exit
  -f FILE, --file=FILE  write report to FILE
  -q, --quiet           don't print status messages to stdout

其中 yourscript 的值是在运行时确定的 (通常来自 sys.argv[0])。

背景

optparse was explicitly designed to encourage the creation of programs with straightforward command-line interfaces that follow the conventions established by the getopt() family of functions available to C developers. To that end, it supports only the most common command-line syntax and semantics conventionally used under Unix. If you are unfamiliar with these conventions, reading this section will allow you to acquaint yourself with them.

术语

argument -- 参数

在命令行中输入的字符串,并会被 shell 传给 execl()execv()。 在 Python 中,参数将是 sys.argv[1:] 的元素 (sys.argv[0] 是被执行的程序的名称)。 Unix shell 也使用术语 "word" 来指代参数。

有时替换 sys.argv[1:] 以外的参数列表也是必要的,所以你应当将 "参数" 当作是 "sys.argv[1:] 的一个元素,或者是作为 sys.argv[1:] 的替代的其他列表"。

选项

an argument used to supply extra information to guide or customize the execution of a program. There are many different syntaxes for options; the traditional Unix syntax is a hyphen ("-") followed by a single letter, e.g. -x or -F. Also, traditional Unix syntax allows multiple options to be merged into a single argument, e.g. -x -F is equivalent to -xF. The GNU project introduced -- followed by a series of hyphen-separated words, e.g. --file or --dry-run. These are the only two option syntaxes provided by optparse.

存在于世上的其他一些选项语法包括:

  • 一个连字符后面跟几个字母,例如 -pf (这与多个选项合并成单个参数 并不 一样)

  • 一个连字符后面跟一个完整单词,例如 -file (这在技术上等同于前面的语法,但它们通常不在同一个程序中出现)

  • 一个加号后面跟一个字母,或几个字母,或一个单词,例如 +f, +rgb

  • 一个斜杠后面跟一个字母,或几个字母,或一个单词,例如 /f, /file

These option syntaxes are not supported by optparse, and they never will be. This is deliberate: the first three are non-standard on any environment, and the last only makes sense if you're exclusively targeting Windows or certain legacy platforms (e.g. VMS, MS-DOS).

可选参数:

an argument that follows an option, is closely associated with that option, and is consumed from the argument list when that option is. With optparse, option arguments may either be in a separate argument from their option:

-f foo
--file foo

或是包括在同一个参数中:

-ffoo
--file=foo

Typically, a given option either takes an argument or it doesn't. Lots of people want an "optional option arguments" feature, meaning that some options will take an argument if they see it, and won't if they don't. This is somewhat controversial, because it makes parsing ambiguous: if -a takes an optional argument and -b is another option entirely, how do we interpret -ab? Because of this ambiguity, optparse does not support this feature.

positional argument -- 位置参数

在解析选项之后,即在选项及其参数解析完成并从参数列表中移除后参数列表中余下的内容。

必选选项

an option that must be supplied on the command-line; note that the phrase "required option" is self-contradictory in English. optparse doesn't prevent you from implementing required options, but doesn't give you much help at it either.

例如,考虑这个假设的命令行:

prog -v --report report.txt foo bar

-v--report 都是选项。 假定 --report 接受一个参数,report.txt 是一个选项参数。 foobar 是位置参数。

选项的作用是什么?

选项被用来提供额外信息以便微调或定制程序的执行。 需要明确的一点是,选项通常都是 可选的。 一个程序应当能在没有设置任何选项的的情况下正常运行。 (从 Unix 或 GNU 工具集中随机挑选一个程序。 它是否能在未设置任何选项的情况下运行并且仍然得到有意义的结果? 主要的例外有 find, tardd --- 它们都是些因为语法不标准和界面混乱而受到公正抨击的变异奇行种。)

有很多人希望他们的程序具有“必需选项”。 请再思考一下。 如果某个项是必需的,那么它就 不是可选的! 如果你的程序必需要有某项信息才能成功运行,则它更适合作为位置参数。

作为良好的命令行界面设计的一个例子,请看基本的用于拷贝文件的 cp 工具。 试图拷贝文件而不提供一个目标和至少一个源是没有什么意义的。 因此,如果你不带参数地运行 cp 它将会报错。 不过,它具有一个完全不需要任何选项的灵活、易用的语法:

cp SOURCE DEST
cp SOURCE ... DEST-DIR

你只使用这个语法就能畅行无阻。 大多数 cp 实现还提供了许多精确调整文件拷贝方式的选项:你可以保留模式和修改时间,避免跟随符号链接,覆盖现有文件之前先询问,诸如此类。 但这些都不会破坏 cp 的核心任务,即将一个文件拷贝为另一个文件,或将多个文件拷贝到另一个目录。

位置参数有什么用?

位置参数是对于你的程序运行来说绝对、肯定需要的信息片段。

一个好的用户界面应当尽可能少地设置绝对必需提供的信息。 如果你的程序必需提供 17 项不同的信息片段才能成功运行,那么你要 如何 从用户获取这些信息将不是问题的关键 --- 大多数人会在他们成功运行此程序之前放弃并离开。 无论用户界面是命令行、配置文件还是 GUI 都一样适用:如果你对你的用户提出如此多的要求,它们大多将会直接放弃。

简而言之,请尽量最小化绝对要求用户提供的信息量 --- 只要有可能就使用合理的默认值。 当然,你希望程序足够灵活也是合理的。 这就是选项的作用。 同样,选项是配置文件中的条目,GUI 中的“首选项”对话框中的控件,还是命令行选项不是问题的关键 --- 你实现的选项越多,你的程序就越灵活,它的具体实现也会变得更为复杂。 当然,太大的灵活性也存在缺点;过多的选项会让用户更难掌握并使你的代码更难维护。

教程

While optparse is quite flexible and powerful, it's also straightforward to use in most cases. This section covers the code patterns that are common to any optparse-based program.

首先,你需要导入 OptionParser 类;然后在主程序的开头部分,创建一个 OptionParser 实例:

from optparse import OptionParser
...
parser = OptionParser()

然后你可以开始定义选项。 基本语法如下:

parser.add_option(opt_str, ...,
                  attr=value, ...)

Each option has one or more option strings, such as -f or --file, and several option attributes that tell optparse what to expect and what to do when it encounters that option on the command line.

通常,每个选项都会有一个短选项字符串和一个长选项字符串,例如

parser.add_option("-f", "--file", ...)

你可以随你的喜好自由定义任意数量的短选项字符串和任意数量的长选项字符串(包括零个),只要总计至少有一个选项字符串。

The option strings passed to OptionParser.add_option() are effectively labels for the option defined by that call. For brevity, we will frequently refer to encountering an option on the command line; in reality, optparse encounters option strings and looks up options from them.

Once all of your options are defined, instruct optparse to parse your program's command line:

(options, args) = parser.parse_args()

(如果你愿意,可以将自定义的参数列表传给 parse_args(),但很少有必要这样做:默认它将使用 sys.argv[1:]。)

parse_args() 返回两个值:

  • options,一个包含你所有的选项的值的对象 --- 举例来说,如果 --file 接受一个字符串参数,则 options.file 将为用户所提供的文件名,或者如果用户未提供该选项则为 None

  • args,由解析选项之后余下的位置参数组成的列表

本教学章节只介绍了四个最重要的选项属性: action, type, dest (destination) 和 help。 其中,action 是最基本的一个。

理解选项动作

Actions tell optparse what to do when it encounters an option on the command line. There is a fixed set of actions hard-coded into optparse; adding new actions is an advanced topic covered in section Extending optparse. Most actions tell optparse to store a value in some variable---for example, take a string from the command line and store it in an attribute of options.

If you don't specify an option action, optparse defaults to store.

store 动作

The most common option action is store, which tells optparse to take the next argument (or the remainder of the current argument), ensure that it is of the correct type, and store it to your chosen destination.

例如:

parser.add_option("-f", "--file",
                  action="store", type="string", dest="filename")

Now let's make up a fake command line and ask optparse to parse it:

args = ["-f", "foo.txt"]
(options, args) = parser.parse_args(args)

When optparse sees the option string -f, it consumes the next argument, foo.txt, and stores it in options.filename. So, after this call to parse_args(), options.filename is "foo.txt".

Some other option types supported by optparse are int and float. Here's an option that expects an integer argument:

parser.add_option("-n", type="int", dest="num")

请注意这个选项没有长选项字符串,这是完全可接受的。 而且,它也没有显式的动作,因为使用默认的 store

让我们解析另一个虚假的命令行。 这一次,我们将让选项参数与选项紧贴在一起:因为 -n42 (一个参数) 与 -n 42 (两个参数) 是等价的,以下代码

(options, args) = parser.parse_args(["-n42"])
print(options.num)

将会打印 42

If you don't specify a type, optparse assumes string. Combined with the fact that the default action is store, that means our first example can be a lot shorter:

parser.add_option("-f", "--file", dest="filename")

If you don't supply a destination, optparse figures out a sensible default from the option strings: if the first long option string is --foo-bar, then the default destination is foo_bar. If there are no long option strings, optparse looks at the first short option string: the default destination for -f is f.

optparse also includes the built-in complex type. Adding types is covered in section Extending optparse.

处理布尔值(旗标)选项

Flag options---set a variable to true or false when a particular option is seen---are quite common. optparse supports them with two separate actions, store_true and store_false. For example, you might have a verbose flag that is turned on with -v and off with -q:

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")

这里我们有两个相同目标的不同选项,这是完全可行的。 (只是这意味着在设置默认值时你必须更加小心 --- 见下文所述。)

When optparse encounters -v on the command line, it sets options.verbose to True; when it encounters -q, options.verbose is set to False.

其他动作

Some other actions supported by optparse are:

"store_const"

存储一个常量值,通过 Option.const 预设

"append"

将此选项的参数添加到一个列表

"count"

让指定的计数器加一

"callback"

调用指定函数

这些在 参考指南,以及 选项回调 等章节中有说明。

默认值

All of the above examples involve setting some variable (the "destination") when certain command-line options are seen. What happens if those options are never seen? Since we didn't supply any defaults, they are all set to None. This is usually fine, but sometimes you want more control. optparse lets you supply a default value for each destination, which is assigned before the command line is parsed.

First, consider the verbose/quiet example. If we want optparse to set verbose to True unless -q is seen, then we can do this:

parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")

由于默认值将应用到 destination 而不是任何特定选项,并且这两个选项正好具有相同的目标,因此这是完全等价的:

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose", default=True)

考虑一下:

parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)

同样地,verbose 的默认值将为 True: 最终生效的将是最后提供给任何特定目标的默认值。

一种更清晰的默认值指定方式是使用 OptionParser 的 set_defaults() 方法,你可以在调用 parse_args() 之前的任何时候调用它:

parser.set_defaults(verbose=True)
parser.add_option(...)
(options, args) = parser.parse_args()

如前面一样,最终生效的将是最后为特定选项目标指定的值。 为清楚起见,请使用一种或另外一种设置默认值的方法,而不要同时使用。

生成帮助

optparse's ability to generate help and usage text automatically is useful for creating user-friendly command-line interfaces. All you have to do is supply a help value for each option, and optionally a short usage message for your whole program. Here's an OptionParser populated with user-friendly (documented) options:

usage = "usage: %prog [options] arg1 arg2"
parser = OptionParser(usage=usage)
parser.add_option("-v", "--verbose",
                  action="store_true", dest="verbose", default=True,
                  help="make lots of noise [default]")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose",
                  help="be vewwy quiet (I'm hunting wabbits)")
parser.add_option("-f", "--filename",
                  metavar="FILE", help="write output to FILE")
parser.add_option("-m", "--mode",
                  default="intermediate",
                  help="interaction mode: novice, intermediate, "
                       "or expert [default: %default]")

If optparse encounters either -h or --help on the command-line, or if you just call parser.print_help(), it prints the following to standard output:

Usage: <yourscript> [options] arg1 arg2

Options:
  -h, --help            show this help message and exit
  -v, --verbose         make lots of noise [default]
  -q, --quiet           be vewwy quiet (I'm hunting wabbits)
  -f FILE, --filename=FILE
                        write output to FILE
  -m MODE, --mode=MODE  interaction mode: novice, intermediate, or
                        expert [default: intermediate]

(If the help output is triggered by a help option, optparse exits after printing the help text.)

There's a lot going on here to help optparse generate the best possible help message:

  • 该脚本定义了自己的用法消息:

    usage = "usage: %prog [options] arg1 arg2"
    

    optparse expands %prog in the usage string to the name of the current program, i.e. os.path.basename(sys.argv[0]). The expanded string is then printed before the detailed option help.

    If you don't supply a usage string, optparse uses a bland but sensible default: "Usage: %prog [options]", which is fine if your script doesn't take any positional arguments.

  • every option defines a help string, and doesn't worry about line-wrapping---optparse takes care of wrapping lines and making the help output look good.

  • 需要接受值的选项会在它们自动生成的帮助消息中提示这一点,例如对于 "mode" 选项:

    -m MODE, --mode=MODE
    

    Here, "MODE" is called the meta-variable: it stands for the argument that the user is expected to supply to -m/--mode. By default, optparse converts the destination variable name to uppercase and uses that for the meta-variable. Sometimes, that's not what you want---for example, the --filename option explicitly sets metavar="FILE", resulting in this automatically generated option description:

    -f FILE, --filename=FILE
    

    不过,这具有比节省一点空间更重要的作用:手动编写的帮助文本使用元变量 FILE 来提示用户在半正式的语法 -f FILE 和非正式的描述 "write output to FILE" 之间存在联系。 这是一种使你的帮助文本更清晰并对最终用户来说更易用的简单而有效的方式。

  • options that have a default value can include %default in the help string---optparse will replace it with str() of the option's default value. If an option has no default value (or the default value is None), %default expands to none.

选项分组

在处理大量选项时,可以方便地将选项进行分组以提供更好的帮助输出。 OptionParser 可以包含多个选项分组,每个分组可以包含多个选项。

选项分组是使用 OptionGroup 类来生成的:

class optparse.OptionGroup(parser, title, description=None)

其中

  • parser 是分组将被插入的 OptionParser 实例

  • title 是分组的标题

  • description,可选项,是分组的长描述文本

OptionGroup 继承自 OptionContainer (类似 OptionParser) 因此 add_option() 方法可被用来向分组添加选项。

一旦声明了所有选项,使用 OptionParser 方法 add_option_group() 即可将分组添加到之前定义的解析器。

继续使用前一节定义的解析器,很容易将 OptionGroup 添加到解析器中:

group = OptionGroup(parser, "Dangerous Options",
                    "Caution: use these options at your own risk.  "
                    "It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)

这将产生以下帮助输出:

Usage: <yourscript> [options] arg1 arg2

Options:
  -h, --help            show this help message and exit
  -v, --verbose         make lots of noise [default]
  -q, --quiet           be vewwy quiet (I'm hunting wabbits)
  -f FILE, --filename=FILE
                        write output to FILE
  -m MODE, --mode=MODE  interaction mode: novice, intermediate, or
                        expert [default: intermediate]

  Dangerous Options:
    Caution: use these options at your own risk.  It is believed that some
    of them bite.

    -g                  Group option.

更完整一些的示例可能涉及使用多个分组:继续扩展之前的例子:

group = OptionGroup(parser, "Dangerous Options",
                    "Caution: use these options at your own risk.  "
                    "It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)

group = OptionGroup(parser, "Debug Options")
group.add_option("-d", "--debug", action="store_true",
                 help="Print debug information")
group.add_option("-s", "--sql", action="store_true",
                 help="Print all SQL statements executed")
group.add_option("-e", action="store_true", help="Print every action done")
parser.add_option_group(group)

这会产生以下输出:

Usage: <yourscript> [options] arg1 arg2

Options:
  -h, --help            show this help message and exit
  -v, --verbose         make lots of noise [default]
  -q, --quiet           be vewwy quiet (I'm hunting wabbits)
  -f FILE, --filename=FILE
                        write output to FILE
  -m MODE, --mode=MODE  interaction mode: novice, intermediate, or expert
                        [default: intermediate]

  Dangerous Options:
    Caution: use these options at your own risk.  It is believed that some
    of them bite.

    -g                  Group option.

  Debug Options:
    -d, --debug         Print debug information
    -s, --sql           Print all SQL statements executed
    -e                  Print every action done

另一个有趣的方法,特别适合在编程处理选项分组时使用:

OptionParser.get_option_group(opt_str)

返回短或长选项字符串 opt_str (例如 '-o''--option') 所属的 OptionGroup。 如果没有对应的 OptionGroup,则返回 None

打印版本字符串

Similar to the brief usage string, optparse can also print a version string for your program. You have to supply the string as the version argument to OptionParser:

parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")

%prog is expanded just like it is in usage. Apart from that, version can contain anything you like. When you supply it, optparse automatically adds a --version option to your parser. If it encounters this option on the command line, it expands your version string (by replacing %prog), prints it to stdout, and exits.

举例来说,如果你的脚本是 /usr/bin/foo:

$ /usr/bin/foo --version
foo 1.0

下列两个方法可被用来打印和获取 version 字符串:

OptionParser.print_version(file=None)

将当前程序的版本消息 (self.version) 打印到 file (默认为 stdout)。 就像 print_usage() 一样,任何在 self.version 中出现的 %prog 将被替换为当前程序的名称。 如果 self.version 为空或未定义则不做任何操作。

OptionParser.get_version()

print_version() 相似但是会返回版本字符串而不是打印它。

How optparse handles errors

There are two broad classes of errors that optparse has to worry about: programmer errors and user errors. Programmer errors are usually erroneous calls to OptionParser.add_option(), e.g. invalid option strings, unknown option attributes, missing option attributes, etc. These are dealt with in the usual way: raise an exception (either optparse.OptionError or TypeError) and let the program crash.

Handling user errors is much more important, since they are guaranteed to happen no matter how stable your code is. optparse can automatically detect some user errors, such as bad option arguments (passing -n 4x where -n takes an integer argument), missing arguments (-n at the end of the command line, where -n takes an argument of any type). Also, you can call OptionParser.error() to signal an application-defined error condition:

(options, args) = parser.parse_args()
...
if options.a and options.b:
    parser.error("options -a and -b are mutually exclusive")

In either case, optparse handles the error the same way: it prints the program's usage message and an error message to standard error and exits with error status 2.

考虑上面的第一个示例,当用户向一个接受整数的选项传入了 4x:

$ /usr/bin/foo -n 4x
Usage: foo [options]

foo: error: option -n: invalid integer value: '4x'

或者,当用户未传入任何值:

$ /usr/bin/foo -n
Usage: foo [options]

foo: error: -n option requires an argument

optparse-generated error messages take care always to mention the option involved in the error; be sure to do the same when calling OptionParser.error() from your application code.

If optparse's default error-handling behaviour does not suit your needs, you'll need to subclass OptionParser and override its exit() and/or error() methods.

合并所有代码

Here's what optparse-based scripts usually look like:

from optparse import OptionParser
...
def main():
    usage = "usage: %prog [options] arg"
    parser = OptionParser(usage)
    parser.add_option("-f", "--file", dest="filename",
                      help="read data from FILENAME")
    parser.add_option("-v", "--verbose",
                      action="store_true", dest="verbose")
    parser.add_option("-q", "--quiet",
                      action="store_false", dest="verbose")
    ...
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.error("incorrect number of arguments")
    if options.verbose:
        print("reading %s..." % options.filename)
    ...

if __name__ == "__main__":
    main()

参考指南

创建解析器

The first step in using optparse is to create an OptionParser instance.

class optparse.OptionParser(...)

OptionParser 构造器没有必需的参数,只有一些可选的关键字参数。 你应当始终以关键字参数形式传入它们,即不要依赖于声明参数所在位置的顺序。

usage (默认: "%prog [options]")

The usage summary to print when your program is run incorrectly or with a help option. When optparse prints the usage string, it expands %prog to os.path.basename(sys.argv[0]) (or to prog if you passed that keyword argument). To suppress a usage message, pass the special value optparse.SUPPRESS_USAGE.

option_list (默认: [])

一个用于填充解析器的由 Option 对象组成的列表。 option_list 中的选项将添加在 standard_option_list (一个可由 OptionParser 的子类设置的类属性) 中的任何选项之后,以及任何版本或帮助选项之前。 已被弃用;请改为在创建解析器之后使用 add_option()

option_class (默认: optparse.Option)

当在 add_option() 中向解析器添加选项时要使用的类。

version (默认: None)

A version string to print when the user supplies a version option. If you supply a true value for version, optparse automatically adds a version option with the single option string --version. The substring %prog is expanded the same as for usage.

conflict_handler (默认: "error")

指定当有相互冲突的选项字符串的选项被添加到解析器时要如何做;参见 选项之间的冲突 一节。

description (默认: None)

A paragraph of text giving a brief overview of your program. optparse reformats this paragraph to fit the current terminal width and prints it when the user requests help (after usage, but before the list of options).

formatter (默认: 一个新的 IndentedHelpFormatter)

An instance of optparse.HelpFormatter that will be used for printing help text. optparse provides two concrete classes for this purpose: IndentedHelpFormatter and TitledHelpFormatter.

add_help_option (默认: True)

If true, optparse will add a help option (with option strings -h and --help) to the parser.

prog

当在 usageversion 中用于代替 os.path.basename(sys.argv[0]) 来扩展 %prog 的字符串。

epilog (默认: None)

一段将在选项帮助之后打印的帮助文本。

填充解析器

有几种方式可以为解析器填充选项。 最推荐的方式是使用 OptionParser.add_option(),如 教程 一节所演示的。 add_option() 可以通过两种方式来调用:

  • 传入一个 Option 实例(即 make_option() 所返回的对象)

  • 传入 make_option() 可接受的(即与 Option 构造器相同的)任意位置和关键字参数组合,它将为你创建 Option 实例

另一种方式是将由预先构造的 Option 实例组成的列表传给 OptionParser 构造器,如下所示:

option_list = [
    make_option("-f", "--filename",
                action="store", type="string", dest="filename"),
    make_option("-q", "--quiet",
                action="store_false", dest="verbose"),
    ]
parser = OptionParser(option_list=option_list)

(make_option() is a factory function for creating Option instances; currently it is an alias for the Option constructor. A future version of optparse may split Option into several classes, and make_option() will pick the right class to instantiate. Do not instantiate Option directly.)

定义选项

每个 Option 实例代表一组同义的命令行选项字符串,例如 -f--file。 你可以指定任意数量的短和长选项字符串,但你必须指定总计至少一个选项字符串。

创建 Option 的正规方式是使用 OptionParseradd_option() 方法。

OptionParser.add_option(option)
OptionParser.add_option(*opt_str, attr=value, ...)

定义只有一个短选项字符串的选项:

parser.add_option("-f", attr=value, ...)

以及定义只有一个长选项字符串的选项:

parser.add_option("--foo", attr=value, ...)

The keyword arguments define attributes of the new Option object. The most important option attribute is action, and it largely determines which other attributes are relevant or required. If you pass irrelevant option attributes, or fail to pass required ones, optparse raises an OptionError exception explaining your mistake.

An option's action determines what optparse does when it encounters this option on the command-line. The standard option actions hard-coded into optparse are:

"store"

存储此选项的参数(默认)

"store_const"

存储一个常量值,通过 Option.const 预设

"store_true"

存储 True

"store_false"

存储 False

"append"

将此选项的参数添加到一个列表

"append_const"

将指定常量值添加到一个列表,可通过 Option.const 预设

"count"

让指定的计数器加一

"callback"

调用指定函数

"help"

打印用法消息,包括所有选项和它们的文档

(如果你没有提供动作,则默认为 "store"。 对于此动作,你还可以提供 typedest 选项属性;参见 标准选项动作。)

As you can see, most actions involve storing or updating a value somewhere. optparse always creates a special object for this, conventionally called options, which is an instance of optparse.Values.

class optparse.Values

一个将被解析的参数名和值作为属性保存的对象。 一般是通过调用 OptionParser.parse_args() 来创建,并可被传给 OptionParser.parse_args()values 参数的自定义子类所覆盖(如在 解析参数 中描述的那样)。

Option 参数(以及各种其他的值)将根据 dest (目标) 选项属性被保存为此对象的属性。

例如,当你调用

parser.parse_args()

one of the first things optparse does is create the options object:

options = Values()

如果该解析器中的某个选项定义带有

parser.add_option("-f", "--file", action="store", type="string", dest="filename")

并且被解析的命令行包括以下任意一项:

-ffoo
-f foo
--file=foo
--file foo

then optparse, on seeing this option, will do the equivalent of

options.filename = "foo"

typedest 选项属性几乎与 action 一样重要,但 action 是唯一对 所有 选项都有意义的。

选项属性

class optparse.Option

一个单独的命令行参数,带有以关键字参数形式传给构造器的各种属性。 通常使用 OptionParser.add_option() 创建而不是直接创建,并可被作为 OptionParseroption_class 参数传入的自定义类来重写。

The following option attributes may be passed as keyword arguments to OptionParser.add_option(). If you pass an option attribute that is not relevant to a particular option, or fail to pass a required option attribute, optparse raises OptionError.

Option.action

(默认: "store")

Determines optparse's behaviour when this option is seen on the command line; the available options are documented here.

Option.type

(默认: "string")

此选项所接受的参数类型 (例如 "string""int");可用的选项类型记录在 这里

Option.dest

(默认: 获取自选项字符串)

If the option's action implies writing or modifying a value somewhere, this tells optparse where to write it: dest names an attribute of the options object that optparse builds as it parses the command line.

Option.default

当未在命令行中遇到此选项时将被用作此选项的目标的值。 另请参阅 OptionParser.set_defaults()

Option.nargs

(默认: 1)

How many arguments of type type should be consumed when this option is seen. If > 1, optparse will store a tuple of values to dest.

Option.const

对于保存常量值的动作,指定要保存的常量值。

Option.choices

对于 "choice" 类型的选项,由用户可选择的字符串组成的列表。

Option.callback

对于使用 "callback" 动作的选项,当遇到此选项时要调用的可调用对象。 请参阅 选项回调 一节了解关于传给可调用对象的参数的详情。

Option.callback_args
Option.callback_kwargs

将在四个标准回调参数之后传给 callback 的额外的位置和关键字参数。

Option.help

当用户提供 help 选项 (如 --help) 之后将在列出所有可有远项时针对此选项打印的文本。 如果没有提供帮助文本,则列出选项时将不附带帮助文本。 要隐藏此选项,请使用特殊值 optparse.SUPPRESS_HELP

Option.metavar

(默认: 获取自选项字符串)

当打印帮助文本时要使用的代表选项参数的名称。 请参阅 教程 一节查看相应示例。

标准选项动作

The various option actions all have slightly different requirements and effects. Most actions have several relevant option attributes which you may specify to guide optparse's behaviour; a few have required attributes, which you must specify for any option using that action.

  • "store" [关联: type, dest, nargs, choices]

    该选项后必须跟一个参数,它将根据 type 被转换为相应的值并保存至 dest。 如果 nargs > 1,则将从命令行读取多个参数;它们将全部根据 type 被转换并以元组形式保存至 dest。 参见 标准选项类型 一节。

    如果提供了 choices (由字符串组成的列表和元组),则类型默认为 "choice"

    如果未提供 type,则默认为 "string"

    If dest is not supplied, optparse derives a destination from the first long option string (e.g., --foo-bar implies foo_bar). If there are no long option strings, optparse derives a destination from the first short option string (e.g., -f implies f).

    示例:

    parser.add_option("-f")
    parser.add_option("-p", type="float", nargs=3, dest="point")
    

    当它解析命令行

    -f foo.txt -p 1 -3.5 4 -fbar.txt
    

    optparse will set

    options.f = "foo.txt"
    options.point = (1.0, -3.5, 4.0)
    options.f = "bar.txt"
    
  • "store_const" [要求: const; 关联: dest]

    const 将存放到 dest 中。

    示例:

    parser.add_option("-q", "--quiet",
                      action="store_const", const=0, dest="verbose")
    parser.add_option("-v", "--verbose",
                      action="store_const", const=1, dest="verbose")
    parser.add_option("--noisy",
                      action="store_const", const=2, dest="verbose")
    

    If --noisy is seen, optparse will set

    options.verbose = 2
    
  • "store_true" [关联: dest]

    True 存放到 dest 中的 "store_const" 的特例。

  • "store_false" [关联: dest]

    类似于 "store_true",但是存放 False

    示例:

    parser.add_option("--clobber", action="store_true", dest="clobber")
    parser.add_option("--no-clobber", action="store_false", dest="clobber")
    
  • "append" [关联: type, dest, nargs, choices]

    The option must be followed by an argument, which is appended to the list in dest. If no default value for dest is supplied, an empty list is automatically created when optparse first encounters this option on the command-line. If nargs > 1, multiple arguments are consumed, and a tuple of length nargs is appended to dest.

    typedest 的默认值与 "store" 动作的相同。

    示例:

    parser.add_option("-t", "--tracks", action="append", type="int")
    

    If -t3 is seen on the command-line, optparse does the equivalent of:

    options.tracks = []
    options.tracks.append(int("3"))
    

    如果,在稍后的时候,再遇到 --tracks=4,它将执行:

    options.tracks.append(int("4"))
    

    append 动作会在选项的当前值上调用 append 方法。 这意味着任何被指定的默认值必须具有 append 方法。 这还意味着如果默认值非空,则其中的默认元素将存在于选项的已解析值中,而任何来自命令行的值将被添加到这些默认值之后:

    >>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults'])
    >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg'])
    >>> opts.files
    ['~/.mypkg/defaults', 'overrides.mypkg']
    
  • "append_const" [需要: const; 关联: dest]

    "store_const" 类似,但 const 值将被添加到 dest;与 "append" 一样,dest 默认为 None,并且当首次遇到该选项时将自动创建一个空列表。

  • "count" [关联: dest]

    对保存在 dest 的整数执行递增。 如果未提供默认值,则 dest 会在第一次执行递增之前被设为零。

    示例:

    parser.add_option("-v", action="count", dest="verbosity")
    

    The first time -v is seen on the command line, optparse does the equivalent of:

    options.verbosity = 0
    options.verbosity += 1
    

    后续每次出现 -v 都将导致

    options.verbosity += 1
    
  • "callback" [需要: callback; 关联: type, nargs, callback_args, callback_kwargs]

    调用 callback 所指定的函数,它将以如下形式被调用

    func(option, opt_str, value, parser, *args, **kwargs)
    

    请参阅 选项回调 一节了解详情。

  • "help"

    为当前选项解析器中所有的选项打印完整帮助消息。 该帮助消息是由传给 OptionParser 的构造器的 usage 字符串和传给每个选项的 help 字符串构造而成的。

    如果没有为某个选项提供 help 字符串,它仍将在帮助消息中列出。 要完全略去某个选项,请使用特殊值 optparse.SUPPRESS_HELP

    optparse automatically adds a help option to all OptionParsers, so you do not normally need to create one.

    示例:

    from optparse import OptionParser, SUPPRESS_HELP
    
    # 通常,help 选项会自动添加,但可以
    # 使用 add_help_option 参数来屏蔽
    parser = OptionParser(add_help_option=False)
    
    parser.add_option("-h", "--help", action="help")
    parser.add_option("-v", action="store_true", dest="verbose",
                      help="Be moderately verbose")
    parser.add_option("--file", dest="filename",
                      help="Input file to read data from")
    parser.add_option("--secret", help=SUPPRESS_HELP)
    

    If optparse sees either -h or --help on the command line, it will print something like the following help message to stdout (assuming sys.argv[0] is "foo.py"):

    Usage: foo.py [options]
    
    Options:
      -h, --help        Show this help message and exit
      -v                Be moderately verbose
      --file=FILENAME   Input file to read data from
    

    After printing the help message, optparse terminates your process with sys.exit(0).

  • "version"

    Prints the version number supplied to the OptionParser to stdout and exits. The version number is actually formatted and printed by the print_version() method of OptionParser. Generally only relevant if the version argument is supplied to the OptionParser constructor. As with help options, you will rarely create version options, since optparse automatically adds them when needed.

标准选项类型

optparse has five built-in option types: "string", "int", "choice", "float" and "complex". If you need to add new option types, see section Extending optparse.

传给 string 类型选项的参数不会以任何方式进行检查或转换:命令行中的文本将被原样保存至目标(或传给回调)。

整数参数 ("int" 类型) 将以如下方式解析:

  • 如果数字开头为 0x,它将被解析为十六进制数

  • 如果数字开头为 0,它将被解析为八进制数

  • 如果数字开头为 0b,它将被解析为二进制数

  • 在其他情况下,数字将被解析为十进制数

The conversion is done by calling int() with the appropriate base (2, 8, 10, or 16). If this fails, so will optparse, although with a more useful error message.

"float""complex" 选项参数会直接通过 float()complex() 来转换,使用类似的错误处理。

"choice" 选项是 "string" 选项的子类型。 choices 选项属性(由字符串组成的序列)定义了允许的选项参数的集合。 optparse.check_choice() 将用户提供的选项参数与这个主列表进行比较并会在给出无效的字符串时引发 OptionValueError

解析参数

创建和填充 OptionParser 的基本目的是调用其 parse_args() 方法。

OptionParser.parse_args(args=None, values=None)

解析 args 中的命令行选项。

输入形参为

args

要处理的参数列表 (默认: sys.argv[1:])

values

要用于存储选项参数的 Values 对象(默认值:一个新的 Values 实例) -- 如果你给出一个现有对象,则不会基于它来初始化选项的默认值。

并且返回值是一个 (options, args) 对,其中

options

the same object that was passed in as values, or the optparse.Values instance created by optparse

args

在所有选项被处理完毕后余下的位置参数

最常见的用法是不提供任何关键字参数。 如果你提供了 values,它将通过重复的 setattr() 调用来修改(大致为每个存储到指定选项目标的选项参数调用一次)并由 parse_args() 返回。

如果 parse_args() 在参数列表中遇到任何错误,它将调用 OptionParser 的 error() 方法并附带适当的最终用户错误消息。 这会完全终结你的进程并将退出状态设为 2 (传统的针对命令行错误的 Unix 退出状态)。

查询和操纵你的选项解析器

选项解析器的默认行为可被轻度地定制,并且你还可以调整你的选项解析器查看实际效果如何。 OptionParser 提供了一些方法来帮助你进行定制:

OptionParser.disable_interspersed_args()

Set parsing to stop on the first non-option. For example, if -a and -b are both simple options that take no arguments, optparse normally accepts this syntax:

prog -a arg1 -b arg2

并会这样处理它

prog -a -b arg1 arg2

要禁用此特性,则调用 disable_interspersed_args()。 这将恢复传统的 Unix 语法,其中选项解析会在第一个非选项参数处停止。

如果你用一个命令处理程序来运行另一个拥有它自己的选项的命令而你希望参确保这些选项不会被混淆就可以使用此方法。 例如,每个命令可能具有不同的选项集合。

OptionParser.enable_interspersed_args()

设置解析不在第一个非选项处停止,允许多个命令行参数的插入相互切换。 这是默认的行为。

OptionParser.get_option(opt_str)

返回具有选项字符串 opt_str 的的 Option 实例,或者如果不存在具有该选项字符串的选项则返回 None

OptionParser.has_option(opt_str)

如果 OptionParser 包含一个具有选项字符串 opt_str 的选项 (例如 -q--verbose) 则返回 True

OptionParser.remove_option(opt_str)

如果 OptionParser 包含一个对应于 opt_str 的选项,则移除该选项。 如果该选项提供了任何其他选项字符串,这些选项字符串将全部不可用。 如果 opt_str 不存在于任何属于此 OptionParser 的选项之中,则会引发 ValueError

选项之间的冲突

如果你不够小心,很容易会定义具有相互冲突的选项字符串的多个选项:

parser.add_option("-n", "--dry-run", ...)
...
parser.add_option("-n", "--noisy", ...)

(当你自定义具有某些标准选项的 OptionParser 时特别容易发生这种情况。)

Every time you add an option, optparse checks for conflicts with existing options. If it finds any, it invokes the current conflict-handling mechanism. You can set the conflict-handling mechanism either in the constructor:

parser = OptionParser(..., conflict_handler=handler)

或是在单独调用中设置:

parser.set_conflict_handler(handler)

可用的冲突处理器有:

"error" (默认)

将选项冲突视为编程错误并引发 OptionConflictError

"resolve"

智能地解决选项冲突(见下文)

举例来说,让我们定义一个智能地解决冲突的 OptionParser 并向其添加相互冲突的选项:

parser = OptionParser(conflict_handler="resolve")
parser.add_option("-n", "--dry-run", ..., help="do no harm")
parser.add_option("-n", "--noisy", ..., help="be noisy")

At this point, optparse detects that a previously added option is already using the -n option string. Since conflict_handler is "resolve", it resolves the situation by removing -n from the earlier option's list of option strings. Now --dry-run is the only way for the user to activate that option. If the user asks for help, the help message will reflect that:

Options:
  --dry-run     do no harm
  ...
  -n, --noisy   be noisy

It's possible to whittle away the option strings for a previously added option until there are none left, and the user has no way of invoking that option from the command-line. In that case, optparse removes that option completely, so it doesn't show up in help text or anywhere else. Carrying on with our existing OptionParser:

parser.add_option("--dry-run", ..., help="new dry-run option")

At this point, the original -n/--dry-run option is no longer accessible, so optparse removes it, leaving this help text:

Options:
  ...
  -n, --noisy   be noisy
  --dry-run     new dry-run option

清理

OptionParser 实例存在一些循环引用。 这对 Python 的垃圾回收器来说应该不是问题,但你可能希望在你完成对 OptionParser 的使用后通过调用其 destroy() 来显式地中断循环引用。 这在可以从你的 OptionParser 访问大型对象图的长期运行应用程序中特别有用。

其他方法

OptionParser 还支持其他一些公有方法:

OptionParser.set_usage(usage)

根据上述的规则为 usage 构造器关键字参数设置用法字符串。 传入 None 将设置默认的用法字符串;使用 optparse.SUPPRESS_USAGE 将屏蔽用法说明。

OptionParser.print_usage(file=None)

将当前程序的用法消息 (self.usage) 打印到 file (默认为 stdout)。 出现在 self.usage 中的字符串 %prog 将全部被替换为当前程序的名称。 如果 self.usage 为空或未定义则不做任何事情。

OptionParser.get_usage()

print_usage() 类似但是将返回用法字符串而不是打印它。

OptionParser.set_defaults(dest=value, ...)

一次性地为多个选项目标设置默认值。 使用 set_defaults() 是为选项设置默认值的推荐方式同,因为多个选项可以共享同一个目标。 举例来说,如果几个 "mode" 选项全部设置了相同的目标,则它们中的任何一个都可以设置默认值,而最终生效的将是最后一次设置的默认值:

parser.add_option("--advanced", action="store_const",
                  dest="mode", const="advanced",
                  default="novice")    # 覆盖下面的设置
parser.add_option("--novice", action="store_const",
                  dest="mode", const="novice",
                  default="advanced")  # 覆盖上面的设置

为避免混淆,请使用 set_defaults():

parser.set_defaults(mode="advanced")
parser.add_option("--advanced", action="store_const",
                  dest="mode", const="advanced")
parser.add_option("--novice", action="store_const",
                  dest="mode", const="novice")

选项回调

When optparse's built-in actions and types aren't quite enough for your needs, you have two choices: extend optparse or define a callback option. Extending optparse is more general, but overkill for a lot of simple cases. Quite often a simple callback is all you need.

定义一个回调选项分为两步:

  • 使用 "callback" 动作定义选项本身

  • 编写回调;它是一个接受至少四个参数的函数(或方法),如下所述

定义回调选项

一般来说,定义回调选项的最简单方式是使用 OptionParser.add_option() 方法。 在 action 之外,你必须指定的唯一选项属性是 callback,即要调用的函数:

parser.add_option("-c", action="callback", callback=my_callback)

callback is a function (or other callable object), so you must have already defined my_callback() when you create this callback option. In this simple case, optparse doesn't even know if -c takes any arguments, which usually means that the option takes no arguments---the mere presence of -c on the command-line is all it needs to know. In some circumstances, though, you might want your callback to consume an arbitrary number of command-line arguments. This is where writing callbacks gets tricky; it's covered later in this section.

optparse always passes four particular arguments to your callback, and it will only pass additional arguments if you specify them via callback_args and callback_kwargs. Thus, the minimal callback function signature is:

def my_callback(option, opt, value, parser):

对传给回调的四个参数的说明见下文。

当你定义回调选项时还可以提供一些其他的选项属性:

type

has its usual meaning: as with the "store" or "append" actions, it instructs optparse to consume one argument and convert it to type. Rather than storing the converted value(s) anywhere, though, optparse passes it to your callback function.

nargs

also has its usual meaning: if it is supplied and > 1, optparse will consume nargs arguments, each of which must be convertible to type. It then passes a tuple of converted values to your callback.

callback_args

一个要传给回调的由额外位置参数组成的元组

callback_kwargs

一个要传给回调的由额外关键字参数组成的字典

回调应当如何调用

所有回调都将使用以下方式调用:

func(option, opt_str, value, parser, *args, **kwargs)

其中

option

是调用该回调的 Option 实例

opt_str

是在触发回调的命令行参数中出现的选项字符串。 (如果使用了长选项的缩写形式,则 opt_str 将为完整规范的选项字符串 --- 举例来说,如果用户在命令行中将 --foo 作为 --foobar 的缩写形式,则 opt_str 将为 "--foobar"。)

value

is the argument to this option seen on the command-line. optparse will only expect an argument if type is set; the type of value will be the type implied by the option's type. If type for this option is None (no argument expected), then value will be None. If nargs > 1, value will be a tuple of values of the appropriate type.

parser

是驱动选项解析过程的 OptionParser 实例,主要作用在于你可以通过其实例属性访问其他一些相关数据:

parser.largs

当前的剩余参数列表,即已被读取但不属于选项或选项参数的参数。 可以任意修改 parser.largs,例如通过向其添加更多的参数。 (该列表将成为 args,即 parse_args() 的第二个返回值。)

parser.rargs

当前的保留参数列表,即移除了 opt_strvalue (如果可用),并且只有在它们之后的参数才会被保留。 可以任意修改 parser.rargs,例如通过读取更多的参数。

parser.values

the object where option values are by default stored (an instance of optparse.OptionValues). This lets callbacks use the same mechanism as the rest of optparse for storing option values; you don't need to mess around with globals or closures. You can also access or modify the value(s) of any options already encountered on the command-line.

args

是一个由通过 callback_args 选项属性提供的任意位置参数组成的元组。

kwargs

是一个由通过 callback_kwargs 提供的任意关键字参数组成的字典。

在回调中引发错误

The callback function should raise OptionValueError if there are any problems with the option or its argument(s). optparse catches this and terminates the program, printing the error message you supply to stderr. Your message should be clear, concise, accurate, and mention the option at fault. Otherwise, the user will have a hard time figuring out what they did wrong.

回调示例 1:最简回调

下面是一个不接受任何参数,只是简单地记录所遇见的选项的回调选项示例:

def record_foo_seen(option, opt_str, value, parser):
    parser.values.saw_foo = True

parser.add_option("--foo", action="callback", callback=record_foo_seen)

当然,你也可以使用 "store_true" 动作做到这一点。

回调示例 2:检查选项顺序

下面是一个更有趣些的示例:当看到 -a 出现时将会记录,而如果它在命令行中出现于 -b 之后则将报告错误。

def check_order(option, opt_str, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use -a after -b")
    parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")

回调示例 3:检查选项顺序(通用)

如果你希望为多个类似的选项重用此回调(设置旗标,并在 -b 已经出现时触发),则需要一些额外工作:它设置的错误消息和旗标必须进行通用化。

def check_order(option, opt_str, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use %s after -b" % opt_str)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')

回调示例 4:检查任意条件

当然,你可以设置任何条件 --- 并不限于检查已定义选项的值。 举例来说,如果你有一个不应当在满月时被调用的选项,你就可以这样做:

def check_moon(option, opt_str, value, parser):
    if is_moon_full():
        raise OptionValueError("%s option invalid when moon is full"
                               % opt_str)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
                  action="callback", callback=check_moon, dest="foo")

(定义 is_moon_full() 的任务将作为留给读者的练习。)

回调示例 5:固定的参数

当你定义接受固定数量参数的 callback 选项时情况会变得更有趣一点。 指定一个 callback 选项接受参数的操作类似于定义一个 "store""append" 选项:如果你定义 type,那么该选项将接受一个必须可被转换为相应类型的参数;如果你进一步定义 nargs,那么该选项将接受 nargs 个参数。

下面是一个模拟了标准 "store" 动作的示例:

def store_value(option, opt_str, value, parser):
    setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
                  action="callback", callback=store_value,
                  type="int", nargs=3, dest="foo")

Note that optparse takes care of consuming 3 arguments and converting them to integers for you; all you have to do is store them. (Or whatever; obviously you don't need a callback for this example.)

回调示例 6:可变的参数

Things get hairy when you want an option to take a variable number of arguments. For this case, you must write a callback, as optparse doesn't provide any built-in capabilities for it. And you have to deal with certain intricacies of conventional Unix command-line parsing that optparse normally handles for you. In particular, callbacks should implement the conventional rules for bare -- and - arguments:

  • --- 都可以作为选项参数

  • 单个 -- (如果不是某个选项的参数): 停止命令行处理并丢弃该 --

  • 单个 - (如果不是某个选项的参数): 停止命令行处理但保留 - (将其添加到 parser.largs)

If you want an option that takes a variable number of arguments, there are several subtle, tricky issues to worry about. The exact implementation you choose will be based on which trade-offs you're willing to make for your application (which is why optparse doesn't support this sort of thing directly).

无论如何,下面是一个对于接受可变参数的选项的回调的尝试:

def vararg_callback(option, opt_str, value, parser):
    assert value is None
    value = []

    def floatable(str):
        try:
            float(str)
            return True
        except ValueError:
            return False

    for arg in parser.rargs:
        # stop on --foo like options
        if arg[:2] == "--" and len(arg) > 2:
            break
        # stop on -a, but not on -3 or -3.0
        if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
            break
        value.append(arg)

    del parser.rargs[:len(value)]
    setattr(parser.values, option.dest, value)

...
parser.add_option("-c", "--callback", dest="vararg_attr",
                  action="callback", callback=vararg_callback)

Extending optparse

Since the two major controlling factors in how optparse interprets command-line options are the action and type of each option, the most likely direction of extension is to add new actions and new types.

添加新的类型

To add new types, you need to define your own subclass of optparse's Option class. This class has a couple of attributes that define optparse's types: TYPES and TYPE_CHECKER.

Option.TYPES

一个由类型名称组成的元组;在你的子类中,简单地定义一个在标准元组基础上构建的新元组 TYPES

Option.TYPE_CHECKER

一个将类型名称映射到类型检查函数的字典。 类型检查函数具有如下签名:

def check_mytype(option, opt, value)

其中 option 是一个 Option 实例,opt 是一个选项字符串 (例如 -f),而 value 是来自命令行的必须被检查并转换为你想要的类型的字符串。 check_mytype() 应当返回假设的类型 mytype 的对象。 类型检查函数所返回的值将最终出现在 OptionParser.parse_args() 所返回的 OptionValues 实例中,或是作为 value 形参传给一个回调。

如果你的类型检查函数遇到任何问题则应当引发 OptionValueErrorOptionValueError 接受一个字符串参数,该参数将被原样传递给 OptionParsererror() 方法,该方法将随后附加程序名称和字符串 "error:" 并在终结进程之前将所有信息打印到 stderr。

Here's a silly example that demonstrates adding a "complex" option type to parse Python-style complex numbers on the command line. (This is even sillier than it used to be, because optparse 1.3 added built-in support for complex numbers, but never mind.)

首先,必要的导入操作:

from copy import copy
from optparse import Option, OptionValueError

你必须先定义自己的类型检查器,因为以后它会被引用(在你的 Option 子类的 TYPE_CHECKER 类属性中):

def check_complex(option, opt, value):
    try:
        return complex(value)
    except ValueError:
        raise OptionValueError(
            "option %s: invalid complex value: %r" % (opt, value))

最后,是 Option 子类:

class MyOption (Option):
    TYPES = Option.TYPES + ("complex",)
    TYPE_CHECKER = copy(Option.TYPE_CHECKER)
    TYPE_CHECKER["complex"] = check_complex

(If we didn't make a copy() of Option.TYPE_CHECKER, we would end up modifying the TYPE_CHECKER attribute of optparse's Option class. This being Python, nothing stops you from doing that except good manners and common sense.)

That's it! Now you can write a script that uses the new option type just like any other optparse-based script, except you have to instruct your OptionParser to use MyOption instead of Option:

parser = OptionParser(option_class=MyOption)
parser.add_option("-c", type="complex")

作为替代选择,你可以构建你自己的选项列表并将它传给 OptionParser;如果你不是以上述方式使用 add_option(),则你不需要告诉 OptionParser 使用哪个选项类:

option_list = [MyOption("-c", action="store", type="complex", dest="c")]
parser = OptionParser(option_list=option_list)

添加新的动作

Adding new actions is a bit trickier, because you have to understand that optparse has a couple of classifications for actions:

"store" 类动作

actions that result in optparse storing a value to an attribute of the current OptionValues instance; these options require a dest attribute to be supplied to the Option constructor.

"typed" 类动作

从命令行接受某个值并预期它是一个特定类型;或者更准确地说,是可被转换为一个特定类型的字符串的动作。 这些选项要求向 Option 构造器提供一个 type 属性。attribute to the constructor.

这些是相互重叠的集合:默认的 "store" 类动作有 "store", "store_const", "append""count",而默认的 "typed" 类动作有 "store", "append""callback"

当你添加一个动作时,你需要将它列在 Option 的以下类属性的至少一个当中以对它进行分类(全部为字符串列表):

Option.ACTIONS

所有动作必须在 ACTIONS 中列出。

Option.STORE_ACTIONS

"store" 类动作要额外地在此列出。

Option.TYPED_ACTIONS

"typed" 类动作要额外地在此列出。

Option.ALWAYS_TYPED_ACTIONS

Actions that always take a type (i.e. whose options always take a value) are additionally listed here. The only effect of this is that optparse assigns the default type, "string", to options with no explicit type whose action is listed in ALWAYS_TYPED_ACTIONS.

为了真正实现你的新动作,你必须重写 Option 的 take_action() 方法并添加一个识别你的动作的分支。

例如,让我们添加一个 "extend" 动作。 它类似于标准的 "append" 动作,但 "extend" 不是从命令行接受单个值并将其添加到现有列表,而是接受形式为以单个逗号分隔的多个值的字符串,并用这些值来扩展现有列表。 也就是说,如果 --names 是一个类型为 "string""extend" 选项,则命令行

--names=foo,bar --names blah --names ding,dong

将得到一个列表

["foo", "bar", "blah", "ding", "dong"]

我们再定义一个 Option 的子类:

class MyOption(Option):

    ACTIONS = Option.ACTIONS + ("extend",)
    STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
    TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
    ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)

    def take_action(self, action, dest, opt, value, values, parser):
        if action == "extend":
            lvalue = value.split(",")
            values.ensure_value(dest, []).extend(lvalue)
        else:
            Option.take_action(
                self, action, dest, opt, value, values, parser)

应注意的特性:

  • "extend" 既预期在命令行接受一个值又会将该值保存到某处,因此它同时被归类于 STORE_ACTIONSTYPED_ACTIONS

  • to ensure that optparse assigns the default type of "string" to "extend" actions, we put the "extend" action in ALWAYS_TYPED_ACTIONS as well.

  • MyOption.take_action() implements just this one new action, and passes control back to Option.take_action() for the standard optparse actions.

  • values 是 optparse_parser.Values 类的一个实例,该类提供了非常有用的 ensure_value() 方法。 ensure_value() 实际就是一个带有安全阀的 getattr();它的调用形式为

    values.ensure_value(attr, value)
    

    如果 valuesattr 属性不存在或为 None,则 ensure_value() 会先将其设为 value,然后返回 value。 这非常适用于 "extend", "append""count" 等动作,它们会将数据累积在一个变量中并预期该变量属于特定的类型(前两项是一个列表,后一项是一个整数)。 使用 ensure_value() 意味着使用你的动作的脚本无需关心为相应的选项目标设置默认值;可以简单地保持默认的 Noneensure_value() 将在必要时负责为其设置适当的值。

异常

exception optparse.OptionError

当使用无效或不一致的参数创建 Option 实例时将被引发。

exception optparse.OptionConflictError

当向 OptionParser 添加相互冲突的选项时将被引发。

exception optparse.OptionValueError

当在命令行中遇到无效的选项值时将被引发。

exception optparse.BadOptionError

当在命令行中传入无效的选项时将被引发。

exception optparse.AmbiguousOptionError

当在命令行中传入有歧义的选项时将被引发。