15.5. optparse —解析器,用于命令行选项

2.3 版的新Function。

从 2.7 版开始不推荐使用:optparse不推荐使用的模块,将不再进行开发。开发将 continue 使用argparse模块。

源代码: Lib/optparse.py


与旧的getopt模块相比,optparse是用于解析命令行选项的更方便,灵活且Function强大的库。 optparse使用更具语句性的命令行解析样式:创建OptionParser的实例,使用选项填充它,然后解析命令行。 optparse允许用户以常规 GNU/POSIX 语法指定选项,并另外为您生成用法和帮助消息。

这是在简单脚本中使用optparse的示例:

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

optparse在解析命令行时,会根据用户提供的命令行值设置parse_args()返回的options对象的属性。当parse_args()从解析此命令行返回时,options.filename将是"outfile",而options.verbose将是Falseoptparse支持长选项和短选项,允许短选项合并在一起,并允许选项以各种方式与其参数关联。因此,以下命令行均等同于上述示例:

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

此外,用户可以运行以下其中一项

<yourscript> -h
<yourscript> --help

optparse将打印出脚本选项的简要摘要:

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

15.5.1. Background

optparse被明确设计为鼓励使用简单,常规的命令行界面来创建程序。为此,它仅支持 Unix 下常规使用的最常见的命令行语法和语义。如果您不熟悉这些约定,请阅读本节以熟悉它们。

15.5.1.1. Terminology

  • argument

    • 在命令行上 Importing 的字符串,由 Shell 程序传递给execl()execv()。在 Python 中,参数是sys.argv[1:]的元素(sys.argv[0]是正在执行的程序的名称)。 UnixShell 也使用术语“单词”。

偶尔需要替换除sys.argv[1:]之外的参数列表,因此您应将“ argument”读为“ sys.argv[1:]的元素,或作为sys.argv[1:]的替代提供的某些其他列表”。

  • option

    • 用于提供额外信息以指导或自定义程序执行的参数。选项有许多不同的语法。传统的 Unix 语法是连字符(-),后接单个字母,例如-x-F。另外,传统的 Unix 语法允许将多个选项合并为一个参数,例如-x -F等效于-xF。 GNU 项目引入了--,后接了一系列用连字符分隔的字词,例如--file--dry-run。这是optparse提供的仅有的两个选项语法。

世界上其他一些可选的语法包括:

  • 连字号后接几个字母,例如-pf(这与多个选项合并为一个参数不同)

  • 连字号后接完整字词,例如-file(从技术上讲,它等效于以前的语法,但是通常不会在同一程序中看到它们)

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

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

optparse不支持这些选项语法,从不支持。这是有意为之的:前三个在任何环境下都是非标准的,后一个仅在您专门针对 VMS,MS-DOS 和/或 Windows 时才有意义。

  • option argument

    • 一个选项后面的参数,与该选项紧密相关,并且在该选项存在时从参数列表中使用。对于optparse,选项参数可以与选项分开位于单独的参数中:
-f foo
--file foo

或包含在同一参数中:

-ffoo
--file=foo

通常,给定选项要么带有参数,要么不带参数。许多人都希望使用“可选选项参数”Function,这意味着某些选项在看到参数时将带有参数,而在没有选项时将不带参数。这有点争议,因为它使解析变得模棱两可:如果-a带有一个可选参数,而-b完全是另一个选项,那么我们如何解释-ab呢?由于存在这种歧义,optparse不支持此Function。

  • positional argument

    • 解析选项后,即解析了选项及其参数并将其从参数列表中删除后,参数列表中剩下的内容。
  • required option

    • 必须在命令行上提供的选项;请注意,短语“ required option”在英语中是自相矛盾的。 optparse不会阻止您实施必需的选项,但也不能给您太多帮助。

例如,考虑以下假设命令行:

prog -v --report report.txt foo bar

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

15.5.1.2. 有什么选择?

选项用于提供其他信息,以调整或自定义程序的执行。如果不清楚,则选项通常为* optional *。一个程序应该能够在没有任何选项的情况下正常运行。 (从 Unix 或 GNU 工具集中选择一个随机程序.它可以在没有任何选项的情况下运行并且仍然有意义吗?主要的 exception 是findtardd,所有这些都是因怪异而被批评的突变体怪兽.-标准语法和令人困惑的接口.)

许多人希望他们的程序具有“必需的选项”。想一想。如果需要,那么它不是“可选”的!如果您的程序绝对需要一条信息才能成功运行,那么这就是位置参数的含义。

作为良好的命令行界面设计的示例,请考虑使用不起眼的cpUtil 来复制文件。try在不提供目的地和至少一个来源的情况下复制文件没有多大意义。因此,如果不使用参数运行cp将会失败。但是,它具有灵活,有用的语法,根本不需要任何选项:

cp SOURCE DEST
cp SOURCE ... DEST-DIR

您可以做到这一点。大多数cp实现提供了许多选项来精确调整文件的复制方式:您可以保留模式和修改时间,避免遵循符号链接,在破坏现有文件之前询问,等等。但是,这些都不会分散cp的核心使命是将一个文件复制到另一个文件,或将几个文件复制到另一个目录。

15.5.1.3. 位置论据是为了什么?

位置参数是程序绝对肯定要运行的那些信息。

一个好的用户界面应具有尽可能少的绝对要求。如果您的程序需要 17 条不同的信息才能成功运行,那么如何从用户那里获取信息就没关系了-大多数人会在成功运行该程序之前放弃并走开。无论用户界面是命令行,配置文件还是 GUI,这都适用:如果您对用户有如此多的要求,则大多数用户只会放弃。

简而言之,请尽量减少用户绝对需要提供的信息量-尽可能使用明智的默认值。当然,您还希望使程序具有一定的灵 Active。那就是选择的目的。同样,它们是配置文件中的条目,GUI 的“首选项”对话框中的小部件还是命令行选项都无关紧要–实现的选项越多,程序就越灵活,并且越复杂它的实现成为。当然,太多的灵 Active 也有缺点。太多的选项会使用户不知所措,并使您的代码难以维护。

15.5.2. Tutorial

optparse非常灵活且Function强大,但在大多数情况下也很容易使用。本节介绍了任何基于optparse的程序所共有的代码模式。

首先,您需要导入 OptionParser 类。然后,在主程序的早期,创建一个 OptionParser 实例:

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

然后,您可以开始定义选项。基本语法为:

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

每个选项都有一个或多个选项字符串,例如-f--file,还有几个选项属性,它们告诉optparse在命令行上遇到该选项时期望什么以及做什么。

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

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

您可以自由定义任意数量的短选项字符串和长选项字符串(包括零),只要总体上至少有一个选项字符串即可。

传递给OptionParser.add_option()的选项字符串实际上是该调用定义的选项的标签。为简洁起见,我们经常在命令行上参考“遇到选项”。实际上,optparse遇到选项字符串并从中查找选项。

定义完所有选项后,请指示optparse解析程序的命令行:

(options, args) = parser.parse_args()

(如果愿意,可以将自定义参数列表传递给parse_args(),但这几乎没有必要:默认情况下,它使用sys.argv[1:].)

parse_args()返回两个值:

  • options,它是包含所有选项值的对象,例如如果--file使用单个字符串参数,则options.file将是用户提供的文件名,或者None如果用户未提供该选项

  • args,解析选项后剩余的位置参数列表

本教程部分仅涵盖四个最重要的选项属性:actiontypedest(目标)和help。其中,action是最基本的。

15.5.2.1. 了解期权行动

动作告诉optparse在命令行上遇到选项时该怎么办。有一组固定的动作被硬编码为optparseExtending optparse部分介绍了添加新操作的高级主题。大多数操作会告诉optparse将值存储在某个变量中,例如,从命令行获取字符串并将其存储在options属性中。

如果您未指定选项操作,则optparse默认为store

15.5.2.2. Store 行动

最常见的选项操作是store,它告诉optparse接受下一个参数(或当前参数的其余部分),确保其类型正确,并将其存储到所选的目标位置。

For example:

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

现在,让我们组成一个伪造的命令行,并要求optparse对其进行解析:

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

optparse看到选项字符串-f时,它将使用下一个参数foo.txt并将其存储在options.filename中。因此,在调用parse_args()之后,options.filename"foo.txt"

optparse支持的其他一些选项类型是intfloat。这是一个需要整数参数的选项:

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

请注意,此选项没有长选项字符串,这是完全可以接受的。另外,由于默认值为store,因此没有明确的操作。

让我们解析另一个伪造的命令行。这次,我们将选项参数与选项卡在一起:由于-n42(一个参数)等价于-n 42(两个参数),因此代码

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

将打印42

如果您未指定类型,则optparse假定为string。结合默认操作为store的事实,这意味着我们的第一个示例可以短很多:

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

如果您不提供目的地,则optparse从选项字符串中找出合理的默认值:如果第一个长选项字符串是--foo-bar,则默认目的地是foo_bar。如果没有长选项字符串,则optparse查看第一个短选项字符串:-f的默认目标是f

optparse还包括内置的longcomplex类型。 Extending optparse部分介绍了添加类型。

15.5.2.3. 处理布尔值(标志)选项

标记选项(在看到特定选项时将变量设置为 true 或 false)非常普遍。 optparsepass两个单独的动作store_truestore_false支持它们。例如,您可能有一个verbose标志,该标志pass-v打开,并pass-q关闭:

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

在这里,我们有两个具有相同目的地的不同选项,这完全可以。 (这只是意味着您在设置默认值时必须小心一点,请参阅下文.)

optparse在命令行上遇到-v时,它将options.verbose设置为True;当遇到-q时,options.verbose设置为False

15.5.2.4. 其他行为

optparse支持的其他一些操作是:

  • "store_const"

    • 存储一个恒定值
  • "append"

    • 将此选项的参数附加到列表中
  • "count"

    • 计数器加一
  • "callback"

    • 调用指定的函数

这些内容在Reference Guide,参考指南和Option Callbacks部分中有介绍。

15.5.2.5. 默认值

所有上述示例都包含在看到某些命令行选项时设置一些变量(“目标”)的情况。如果这些选项从未出现会怎样?由于我们没有提供任何默认值,因此它们都设置为None。通常这很好,但有时您需要更多控制权。 optparse使您可以为每个目标提供默认值,该默认值是在解析命令行之前分配的。

首先,考虑详细/安静的示例。如果我们希望optparseverbose设置为True,除非看到-q,那么我们可以这样做:

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)

Consider this:

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

与以前一样,为给定的选项目标指定的最后一个值是重要的值。为了清楚起见,请try使用一种或多种设置默认值的方法,而不是同时使用这两种方法。

15.5.2.6. 产生帮助

optparse自动生成帮助和用法文本的Function对于创建用户友好的命令行界面很有用。您要做的就是为每个选项提供help值,并为整个程序提供简短的用法消息。这是一个填充了用户友好的(已记录的)选项的 OptionParser:

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

如果optparse在命令行上遇到-h--help,或者您只是调用parser.print_help(),它将以下内容输出到标准输出:

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]

(如果帮助输出由帮助选项触发,则在打印帮助文本后optparse退出。)

这里有很多事情可以帮助optparse生成最好的帮助消息:

  • 该脚本定义了自己的用法消息:
usage = "usage: %prog [options] arg1 arg2"

optparse将用法字符串中的%prog扩展为当前程序的名称,即os.path.basename(sys.argv[0])。然后在详细选项帮助之前打印扩展的字符串。

如果您不提供用法字符串,则optparse使用平淡但明智的默认值:"Usage: %prog [options]",这在脚本中不使用任何位置参数的情况下很好。

  • 每个选项都定义了一个帮助字符串,并且不必担心换行— optparse负责换行,并使帮助输出看起来不错。

  • 带有值的选项会在其自动生成的帮助消息中表明这一事实,例如对于“模式”选项:

-m MODE, --mode=MODE

在这里,“ MODE”被称为元变量:它代表希望用户提供给-m/--mode的参数。默认情况下,optparse将目标变量名转换为大写并将其用于元变量。有时,这不是您想要的,例如,--filename选项显式设置metavar="FILE",从而产生以下自动生成的选项说明:

-f FILE, --filename=FILE

不过,这不仅节省空间,还很重要:手动编写的帮助文本使用元变量FILE来提示用户,因为半正式语法-f FILE与非正式语义描述“将输出写入 FILE”之间存在联系。这是一种简单而有效的方法,可以使您的帮助 Literals 更加清晰,对finally用户更有用。

2.4 版中的新增Function:具有默认值的选项可以在帮助字符串中包含%defaultoptparse将替换为该选项默认值的str()。如果选项没有默认值(或默认值为None),则%default扩展为none

15.5.2.6.1. 分组选项

当处理许多选项时,将这些选项组合在一起以获得更好的帮助输出很方便。 OptionParser可以包含多个选项组,每个选项组可以包含多个选项。

使用类OptionGroup获得选项组:

    • class * optparse. OptionGroup(* parser title description = None *)
    • where
  • 解析器是要插入该组的OptionParser实例

  • title 是组标题

  • description(可选)是该组的详细描述

OptionGroup继承自OptionContainer(如OptionParser),因此add_option()方法可用于向该组添加选项。

语句所有选项后,使用OptionParser方法add_option_group()将组添加到先前定义的解析器中。

continue 上一节中定义的解析器,向解析器添加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

15.5.2.7. 打印版本字符串

与简短用法字符串相似,optparse也可以为您的程序打印版本字符串。您必须将字符串作为 OptionParser 的version参数提供:

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

%prog就像usage一样展开。除此之外,version可以包含您喜欢的任何内容。提供它时,optparse会自动向解析器添加--version选项。如果在命令行上遇到此选项,它将扩展version字符串(pass替换%prog),将其打印到 stdout 并退出。

例如,如果您的脚本名为/usr/bin/foo

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

以下两种方法可用于打印和获取version字符串:

  • OptionParser. print_version(* file = None *)

    • 将当前程序的版本消息(self.version)打印到* file *(默认标准输出)。与print_usage()一样,self.version中出现的%prog都将替换为当前程序的名称。如果self.version为空或未定义,则不执行任何操作。
  • OptionParser. get_version ( )

15.5.2.8. optparse 如何处理错误

optparse必须担心的错误有两大类:程序员错误和用户错误。程序员错误通常是对OptionParser.add_option()的错误调用,例如无效的选项字符串,未知的选项属性,缺少的选项属性等。这些通常pass以下方式处理:引发异常(optparse.OptionErrorTypeError)并使程序崩溃。

处理用户错误更为重要,因为无论您的代码多么稳定,都可以保证它们会发生。 optparse可以自动检测某些用户错误,例如错误的选项参数(传递-n 4x,其中-n使用整数参数),缺少参数(在命令行末尾-n,其中-n接受任何类型的参数)。另外,您可以调用OptionParser.error()来指示应用程序定义的错误情况:

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

无论哪种情况,optparse都以相同的方式处理错误:它将程序的用法消息和错误消息打印为标准错误,并以错误状态 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-生成的错误消息始终注意提及错误中涉及的选项;请确保从您的应用程序代码调用OptionParser.error()时执行相同的操作。

如果optparse的默认错误处理行为不符合您的需求,则需要子类化 OptionParser 并覆盖其exit()和/或error()方法。

15.5.2.9. 放在一起

基于optparse的脚本通常如下所示:

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

15.5.3. 参考指南

15.5.3.1. 创建解析器

使用optparse的第一步是创建 OptionParser 实例。

  • 类别 optparse. OptionParser(* ... *)

    • OptionParser 构造函数没有必需的参数,但是有许多可选的关键字参数。您应始终将它们作为关键字参数传递,即,不要依赖于参数语句的 Sequences。
  • usage(默认值:"%prog [options]")

    • 在程序运行不正确或带有帮助选项时要打印的使用情况摘要。 optparse打印用法字符串时,它将%prog扩展为os.path.basename(sys.argv[0])(如果您传递了该关键字参数,则扩展为prog)。要禁止使用消息,请传递特殊值optparse.SUPPRESS_USAGE

    • option_list(默认值:[])

      • 用于填充解析器的 Option 对象的列表。 option_list中的选项添加在standard_option_list中的任何选项之后(OptionParser 子类可以设置的类属性),但在任何版本或帮助选项之前。不推荐使用;创建解析器后,请使用add_option()
    • option_class(默认值:optparse.Option)

      • add_option()中向解析器添加选项时使用的类。
    • version(默认值:None)

      • 用户提供版本选项时要打印的版本字符串。如果您为version提供了一个真值,则optparse会自动使用单个选项字符串--version添加一个版本选项。子字符串%progusage一样扩展。
    • conflict_handler(默认值:"error")

      • 指定将具有冲突的选项字符串的选项添加到解析器时的操作;参见第选项之间的冲突节。
    • description(默认值:None)

      • 一段 Literals,简要介绍了您的程序。 optparse重新格式化此段落以适合当前终端宽度,并在用户请求帮助时(在usage之后,但在选项列表之前)打印该段落。
    • formatter(默认值:新的IndentedHelpFormatter)

      • optparse.HelpFormatter 的实例,将用于打印帮助文本。 optparse为此提供了两个具体的类:IndentedHelpFormatter 和 TitledHelpFormatter。
    • add_help_option(默认值:True)

      • 如果为 true,则optparse将帮助选项(带有选项字符串-h--help)添加到解析器。
    • prog

      • usageversion而不是os.path.basename(sys.argv[0])中扩展%prog时使用的字符串。
    • epilog(默认值:None)

      • 选项帮助后要打印的一段帮助文本。

15.5.3.2. 填充解析器

有几种方法可以用选项填充解析器。首选方法是使用OptionParser.add_option(),如Tutorial部分所示。可以pass以下两种方式之一调用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()是用于创建 Option 实例的工厂函数;当前它是 Option 构造函数的别名.optparse的 Future 版本可能会将 Option 分成几个类,而make_option()将选择合适的类进行实例化。请勿直接实例化 Option。)

15.5.3.3. 定义选项

每个 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, ...)

关键字参数定义新的 Option 对象的属性。最重要的选项属性是action,它在很大程度上决定了哪些其他相关或必需的属性。如果您传递了不相关的选项属性,或者未能传递必需的选项属性,则optparse会引发OptionError异常,解释您的错误。

选项的* action *决定optparse在命令行上遇到此选项时将执行的操作。硬编码到optparse的标准选项操作是:

  • "store"

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

    • "store_const"

      • 存储一个恒定值
    • "store_true"

      • 储存真实价值
    • "store_false"

      • 存储一个错误的值
    • "append"

      • 将此选项的参数附加到列表中
    • "append_const"

      • 将常量值添加到列表
    • "count"

      • 计数器加一
    • "callback"

      • 调用指定的函数
    • "help"

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

(如果不提供操作,则默认值为"store".对于此操作,还可以提供typedest选项属性;请参见标准期权行动。)

如您所见,大多数操作都涉及在某个地方存储或更新值。 optparse为此总是创建一个特殊的对象,通常称为options(它恰好是optparse.Values的实例)。根据dest(目标)选项属性,选项参数(和其他各种值)作为该对象的属性存储。

例如,当您致电

parser.parse_args()

optparse要做的第一件事之一就是创建options对象:

options = Values()

如果此解析器中的一个选项定义为

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

并且正在分析的命令行包括以下任何一项:

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

然后optparse(看到此选项)将执行以下操作:

options.filename = "foo"

typedest选项属性几乎与action一样重要,但是action是唯Pair* all *选项有意义的属性。

15.5.3.4. 选项属性

以下选项属性可以作为关键字参数传递给OptionParser.add_option()。如果您传递的选项属性与特定选项无关,或者未能传递必需的选项属性,则optparse引发OptionError

  • Option. action
    • (默认值:"store")

确定在命令行上看到此选项时optparse的行为;可用选项记录在here中。

  • Option. type
    • (默认值:"string")

此选项期望的参数类型(例如"string""int");可用的选项类型记录在here中。

  • Option. dest
    • (默认值:从选项字符串派生)

如果该选项的动作暗示在某个位置写入或修改值,则将告诉optparse写入位置:dest命名optparse解析命令行时生成的options对象的属性。

  • Option. default

  • Option. nargs

    • (default: 1)

看到此选项后,应消耗多少个type类型的参数。如果> 1,则optparse将值 Tuples 存储到dest

  • Option. const

    • 对于存储常数值的动作,要存储的常数值。
  • Option. choices

    • 对于类型"choice"的选项,用户可以从中选择字符串列表。
  • Option. callback

    • 对于具有动作"callback"的选项,当看到该选项时可调用。有关传递给可调用对象的参数的详细信息,请参见Option Callbacks部分。
  • Option. callback_args

  • Option. callback_kwargs

    • 在四个标准回调参数之后,其他位置和关键字参数将传递给callback
  • Option. help

    • 当用户提供help选项(例如--help)后列出所有可用选项时,将为该选项打印帮助文本。如果没有提供帮助文本,则该选项将不带帮助文本列出。要隐藏此选项,请使用特殊值optparse.SUPPRESS_HELP
  • Option. metavar

    • (默认值:从选项字符串派生)

用于打印帮助文本时使用的选项参数的替代。有关示例,请参见第Tutorial节。

15.5.3.5. 标准期权行动

各种选项操作都有不同的要求和效果。大多数操作具有几个相关的选项属性,您可以指定这些属性来指导optparse的行为;一些具有必需的属性,您必须使用该操作为任何选项指定这些属性。

该选项后必须跟一个参数,该参数根据type转换为值并存储在dest中。如果nargs> 1,则将从命令行使用多个参数;全部将根据type进行转换,并作为 Tuples 存储到dest中。参见标准选项类型部分。

如果提供了choices(字符串列表或 Tuples),则类型默认为"choice"

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

如果未提供dest,则optparse会从第一个长选项字符串中得出目标位置(例如--foo-bar表示foo_bar)。如果没有长选项字符串,则optparse从第一个短选项字符串得出目标(例如-f表示f)。

Example:

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将设置

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

const存储在dest中。

Example:

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

如果看到--noisy,则设置optparse

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

"store_const"的特例是将真实值存储到dest

  • "store_false"[relevant: dest]

类似于"store_true",但存储一个假值。

Example:

parser.add_option("--clobber", action="store_true", dest="clobber")
parser.add_option("--no-clobber", action="store_false", dest="clobber")

该选项后必须跟一个参数,该参数将附加到dest的列表中。如果未提供dest的默认值,则optparse首次在命令行上遇到此选项时,将自动创建一个空列表。如果nargs> 1,则使用多个参数,并将长度为nargs的 Tuples 附加到dest

typedest的默认设置与"store"操作的默认设置相同。

Example:

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

如果在命令行上看到-t3,则optparse等效于:

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"[required: const;相关:dest]

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

  • "count"[relevant: dest]

递增存储在dest处的整数。如果未提供默认值,则在第一次增加之前将dest设置为零。

Example:

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

第一次在命令行上看到-voptparse等效于:

options.verbosity = 0
options.verbosity += 1

随后发生的-v导致

options.verbosity += 1

调用callback指定的函数,该函数称为

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

有关更多详细信息,请参见第Option Callbacks节。

  • "help"

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

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

optparse自动将help选项添加到所有 OptionParsers 中,因此通常不需要创建一个。

Example:

from optparse import OptionParser, SUPPRESS_HELP

# usually, a help option is added automatically, but that can
# be suppressed using the add_help_option argument
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)

如果optparse在命令行上看到-h--help,它将在标准输出中打印类似以下帮助消息的内容(假设sys.argv[0]"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

打印帮助消息后,optparsesys.exit(0)终止过程。

  • "version"

将提供给 OptionParser 的版本号打印到 stdout 并退出。版本号实际上是pass OptionParser 的print_version()方法格式化和打印的。通常仅在将version参数提供给 OptionParser 构造函数时才相关。与help选项一样,您几乎不会创建version选项,因为optparse会在需要时自动添加它们。

15.5.3.6. 标准选项类型

optparse具有六种内置选项类型:"string""int""long""choice""float""complex"。如果您需要添加新的选项类型,请参见Extending optparse部分。

不会以任何方式检查或转换字符串选项的参数:命令行上的文本按原样存储在目标中(或传递到回调中)。

整数参数(类型"int""long")的解析如下:

  • 如果数字以0x开头,则将其解析为十六进制数字

  • 如果数字以0开头,则将其解析为八进制数字

  • 如果数字以0b开头,则将其解析为二进制数

  • 否则,该数字将解析为十进制数字

pass使用适当的基数(2、8、10 或 16)调用int()long()来完成转换。如果失败,optparse也会失败,尽管会有更有用的错误消息。

"float""complex"选项参数直接passfloat()complex()进行转换,并具有类似的错误处理方式。

"choice"选项是"string"选项的子类型。 choices选项属性(字符串序列)定义了一组允许的选项参数。 optparse.check_choice()将用户提供的选项参数与此主列表进行比较,如果给出了无效的字符串,则引发OptionValueError

15.5.3.7. 解析参数

创建和填充 OptionParser 的全部目的是调用其parse_args()方法:

(options, args) = parser.parse_args(args=None, values=None)

Importing 参数在哪里

  • args

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

    • 一个用于存储选项参数的optparse.Values对象(默认值:Values的新实例)–如果提供现有对象,则不会在其上初始化选项默认值

和返回值是

  • options

    • valuesoptparse创建的 optparse.Values 实例传入的对象相同
  • args

    • 处理完所有选项后剩余的位置参数

最常见的用法是不提供任何关键字参数。如果提供values,它将pass重复的setattr()调用进行修改(对于存储到选项目标的每个选项参数大约一个),并由parse_args()返回。

如果parse_args()在参数列表中遇到任何错误,它将使用适当的finally用户错误消息调用 OptionParser 的error()方法。这finally以退出状态 2(命令行错误的传统 Unix 退出状态)终止您的进程。

15.5.3.8. 查询和操作您的选项解析器

选项解析器的默认行为可以稍作自定义,您也可以在选项解析器周围四处查看,看看其中有什么。 OptionParser 提供了几种方法来帮助您:

  • OptionParser. disable_interspersed_args ( )
    • 将解析设置为在第一个非选项上停止。例如,如果-a-b都是不带参数的简单选项,则optparse通常接受以下语法:
prog -a arg1 -b arg2

并将其等同于

prog -a -b arg1 arg2

要禁用此Function,请致电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 的选项,则该选项将被删除。如果该选项提供了其他任何选项字符串,则所有这些选项字符串都将变为无效。如果在属于此OptionParser的任何选项中未出现 opt_str *,则引发ValueError

15.5.3.9. 选项之间的冲突

如果您不小心,可以很容易地用冲突的选项字符串定义选项:

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

(如果您已经使用一些标准选项定义了自己的 OptionParser 子类,则尤其如此.)

每次添加选项时,optparse都会检查与现有选项的冲突。如果找到任何内容,它将调用当前的冲突处理机制。您可以在构造函数中设置冲突处理机制:

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

或单独致电:

parser.set_conflict_handler(handler)

可用的冲突处理程序为:

Note

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

此时,optparse检测到先前添加的选项已在使用-n选项字符串。由于conflict_handler"resolve",因此可以pass从较早的选项的选项字符串列表中删除-n来解决这种情况。现在--dry-run是用户激活该选项的唯一方法。如果用户要求帮助,则帮助消息将反映以下内容:

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

可以减少先前添加的选项的选项字符串,直到没有剩余为止,并且用户无法从命令行调用该选项。在这种情况下,optparse会完全删除该选项,因此它不会显示在帮助文本或其他任何地方。continue 使用我们现有的 OptionParser:

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

此时,不再可以访问原始的-n/--dry-run选项,因此optparse将其删除,并保留以下帮助文本:

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

15.5.3.10. Cleanup

OptionParser 实例具有多个循环引用。对于 Python 的垃圾回收器来说,这应该不是问题,但是您可能希望pass在 OptionParser 上调用destroy()来明确地破坏循环引用。这在长时间运行的应用程序中特别有用,在该应用程序中,可以从 OptionParser 访问大型对象图。

15.5.3.11. 其他方法

OptionParser 支持其他几种公共方法:

  • OptionParser. set_usage(用法)

    • 根据上面针对usage构造函数关键字参数所述的规则来设置用法字符串。传递None设置默认用法字符串;使用optparse.SUPPRESS_USAGE禁止使用消息。
  • OptionParser. print_usage(* file = None *)

    • 将当前程序的使用消息(self.usage)打印到* file *(默认标准输出)。 self.usage中出现的任何字符串%prog都将替换为当前程序的名称。如果self.usage为空或未定义,则不执行任何操作。
  • OptionParser. get_usage ( )

    • print_usage()相同,但返回用法字符串而不是打印它。
  • OptionParser. set_defaults(* dest = value ... *)

    • 一次为多个选项目的地设置默认值。使用set_defaults()是设置选项默认值的首选方法,因为多个选项可以共享同一目的地。例如,如果几个“模式”选项都设置了相同的目的地,则其中任何一个都可以设置默认目的地,最后一个赢:
parser.add_option("--advanced", action="store_const",
                  dest="mode", const="advanced",
                  default="novice")    # overridden below
parser.add_option("--novice", action="store_const",
                  dest="mode", const="novice",
                  default="advanced")  # overrides above setting

为避免混淆,请使用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")

15.5.4. 期权回调

optparse的内置动作和类型不足以满足您的需要时,您有两种选择:扩展optparse或定义回调选项。扩展optparse较为笼统,但在许多简单情况下就显得过分了。通常,您只需要一个简单的回调即可。

定义回调选项有两个步骤:

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

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

15.5.4.1. 定义回调选项

与往常一样,定义回调选项的最简单方法是使用OptionParser.add_option()方法。除了action,您必须指定的唯一选项属性是callback,该函数要调用:

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

callback是一个函数(或其他可调用对象),因此在创建此回调选项时必须已定义my_callback()。在这种简单情况下,optparse甚至不知道-c是否接受任何参数,这通常意味着该选项不接受任何参数-仅需要知道-c在命令行中的存在即可。但是,在某些情况下,您可能希望回调使用任意数量的命令行参数。这就是编写回调的棘手之处。本节稍后将介绍。

optparse始终将四个特定参数传递给您的回调,并且仅当您passcallback_argscallback_kwargs指定它们时,才会传递其他参数。因此,最小回调函数签名为:

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

回调的四个参数如下所述。

定义回调选项时,还可以提供其他几个选项属性:

  • type

    • 具有其通常的含义:与"store""append"动作一样,它指示optparse使用一个参数并将其转换为typeoptparse而不是将转换后的值存储在任何地方,而是将其传递给回调函数。
  • nargs

    • 也有其通常的含义:如果提供且大于 1,则optparse将使用nargs参数,每个参数必须可转换为type。然后,它将转换后的值的 Tuples 传递给您的回调。
  • callback_args

    • 传递给回调的额外位置参数的 Tuples
  • callback_kwargs

    • 额外的关键字参数字典,以传递给回调

15.5.4.2. 回调的调用方式

所有回调均如下调用:

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

where

  • option

    • 是调用回调的 Option 实例
  • opt_str

    • 是在命令行上看到的用于触发回调的选项字符串。 (如果使用了缩写的 long 选项,则opt_str将是完整的规范选项字符串-例如,如果用户在命令行上将--foo作为--foobar的缩写,则opt_str将是"--foobar".)
  • value

    • 是在命令行上看到的此选项的参数。如果设置了type,则optparse仅会接受参数; value的类型将是选项类型所隐含的类型。如果此选项的typeNone(没有自变量),则value将是None。如果nargs> 1,则value将是适当类型的值的 Tuples。
  • parser

    • 是驱动整个过程的 OptionParser 实例,主要有用,因为您可以pass其实例属性访问其他一些有趣的数据:
  • parser.largs

    • 当前剩余参数列表,即。已消耗但既不是选项也不是选项参数的参数。随时修改parser.largs,例如pass添加更多参数。 (此列表将成为args,第二个返回值parse_args().)

    • parser.rargs

      • 当前剩余参数列表,即。并删除了opt_strvalue(如果适用),并且仅保留它们后面的参数。随意修改parser.rargs,例如pass消耗更多的参数。
    • parser.values

      • 默认情况下存储选项值的对象(optparse.OptionValues 的实例)。这使回调函数可以使用与optparse的其余部分相同的机制来存储选项值。您无需弄乱全局变量或闭包。您还可以访问或修改命令行中已经遇到的任何选项的值。
  • args

    • 是passcallback_args选项属性提供的任意位置参数的 Tuples。
  • kwargs

15.5.4.3. 在回调中引发错误

如果选项或其参数有任何问题,则回调函数应引发OptionValueErroroptparse捕获到该错误并终止程序,并打印您提供给 stderr 的错误消息。您的消息应该清晰,简洁,准确,并提及错误的选项。否则,用户将很难找出他们做错了什么。

15.5.4.4. 回调示例 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"操作。

15.5.4.5. 回调示例 2:检查选项 Sequences

这是一个稍微有趣的示例:记录见到-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")

15.5.4.6. 回调示例 3:检查选项 Sequences(通用)

如果要将此回调用于几个类似的选项(设置一个标志,但是如果已经看到-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')

15.5.4.7. 回调示例 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()的定义留给 Reader 练习.)

15.5.4.8. 回调示例 5:固定参数

当您定义带有固定数量参数的回调选项时,事情会变得更加有趣。指定回调选项接受参数类似于定义"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")

请注意,optparse会处理 3 个参数,并为您将它们转换为整数。您所要做的就是存储它们。 (或其他任何方法;显然,此示例不需要回调.)

15.5.4.9. 回调示例 6:可变参数

当您希望选项接受可变数量的参数时,事情变得很棘手。在这种情况下,您必须编写一个回调,因为optparse没有为其提供任何内置Function。而且,您必须处理optparse通常为您处理的某些复杂的常规 Unix 命令行解析。特别是,回调应针对裸机---参数实现常规规则:

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

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

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

如果您想要一个带有可变数量参数的选项,则需要考虑一些细微,棘手的问题。您选择的确切实现将基于您愿意为应用程序做出哪些折衷(这就是optparse不直接支持这种事情的原因)。

不过,这是带有变量参数的选项的回调中的刺伤:

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)

15.5.5. 扩展 optparse

由于optparse解释命令行选项的方式的两个主要控制因素是每个选项的操作和类型,因此扩展的最可能方向是添加新的操作和新的类型。

15.5.5.1. 添加新类型

要添加新类型,您需要定义自己的optparseOption类的子类。此类具有几个定义optparse的类型的属性:TYPESTYPE_CHECKER

  • Option. TYPES

    • 类型名称的 Tuples;在子类中,只需定义一个基于标准 Tuples 的新 TuplesTYPES即可。
  • Option. TYPE_CHECKER

    • 字典将类型名称 Map 到类型检查Function。类型检查Function具有以下签名:
def check_mytype(option, opt, value)

其中optionOption实例,opt是选项字符串(例如-f),而value是命令行中必须检查并转换为所需类型的字符串。 check_mytype()应该返回假设类型mytype的对象。类型检查函数返回的值将出现在OptionParser.parse_args()返回的 OptionValues 实例中,或者作为value参数传递给回调。

如果遇到任何问题,您的类型检查函数应引发OptionValueErrorOptionValueError接受一个字符串参数,该参数按原样传递给OptionParsererror()方法,该方法又在程序名和字符串"error:"之前加了前缀,并在终止进程之前将所有内容打印到 stderr。

这是一个愚蠢的示例,演示了在命令行上添加"complex"选项类型以解析 Python 样式的复数。 (这比以前更加愚蠢,因为optparse 1.3 添加了对复数的内置支持,但是没关系。)

首先,必要的 import:

from copy import copy
from optparse import Option, OptionValueError

您需要先定义类型检查器,因为稍后会提到它(在 Option 子类的TYPE_CHECKER class 属性中):

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

(如果我们不将copy()设为Option.TYPE_CHECKER,那么finally将修改optparse的 Option 类的TYPE_CHECKER属性。这是 Python,除了良好的举止和常识之外,没有什么阻止您这样做的。)

而已!现在,您可以编写一个使用新选项类型的脚本,就像其他任何基于optparse的脚本一样,除了必须指示 OptionParser 使用 MyOption 而不是 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)

15.5.5.2. 添加新动作

添加新操作有点棘手,因为您必须了解optparse对操作进行了两种分类:

  • "store" actions

    • 导致optparse将值存储到当前 OptionValues 实例的属性的操作;这些选项需要将dest属性提供给 Option 构造函数。
  • "typed" actions

    • 从命令行获取值并期望其具有某种类型的操作;或者更确切地说,是可以转换为特定类型的字符串。这些选项要求 Option 构造函数具有type属性。

这些是重叠的集合:一些默认的“存储”操作是"store""store_const""append""count",而默认的“类型化”操作是"store""append""callback"

添加操作时,需要pass将其列出在 Option 的以下至少一个类属性中(所有都是字符串列表)来对其进行分类:

  • Option. ACTIONS

    • 必须在“操作”中列出所有操作。
  • Option. STORE_ACTIONS

    • 这里还列出了“存储”操作。
  • Option. TYPED_ACTIONS

    • 这里还列出了“类型化”动作。
  • Option. ALWAYS_TYPED_ACTIONS

    • 此处始终列出始终采用某种类型(即其选项始终采用值)的操作。唯一的效果是optparse将默认类型"string"分配给没有明确类型的选项,而其操作列在ALWAYS_TYPED_ACTIONS中。

为了实际执行您的新操作,您必须覆盖 Option 的take_action()方法,并添加一个识别您的操作的案例。

例如,让我们添加一个"extend"动作。这与标准"append"操作类似,但是"extend"不会在命令行中获取单个值并将其附加到现有列表中,而是在单个逗号分隔的字符串中获取多个值,并使用它们扩展现有列表。也就是说,如果--names是类型"string""extend"选项,则命令行

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

会产生一个 Lists

["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"都希望在命令行上 Importing 一个值,并将该值存储在某个位置,因此它都放在STORE_ACTIONSTYPED_ACTIONS中。

  • 为了确保optparse"string"的默认类型分配给"extend"动作,我们也将"extend"动作也放在ALWAYS_TYPED_ACTIONS中。

  • MyOption.take_action()仅实现了这一新操作,然后将控制权传回Option.take_action()以进行标准optparse动作。

  • values是 optparse_parser.Values 类的实例,该类提供了非常有用的ensure_value()方法。 ensure_value()本质上是带有安全阀的getattr();它被称为

values.ensure_value(attr, value)

如果valuesattr属性不存在或为None,则 sure_value()首先将其设置为value,然后返回'value。这对于"extend""append""count"之类的操作非常方便,它们全部将数据存储在变量中,并期望该变量具有某种类型(前两个的列表,后一个为整数)。使用ensure_value()意味着使用您的操作的脚本不必担心为所讨论的选项目标设置默认值。他们可以保留默认值,因为None,而ensure_value()会在需要时妥善处理。