optparse — 命令行选项解析器¶
源代码: Lib/optparse.py
optparse 是一个比旧的 getopt 模块更方便、灵活和强大的命令行选项解析库。 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 将为 False。 optparse 支持长选项和短选项,允许将短选项合并在一起,并允许以多种方式将选项与其参数关联起来。因此,以下命令行都等效于上面的示例
<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])。
背景¶
optparse 是专门为鼓励创建具有简单、传统命令行界面的程序而设计的。为此,它只支持在 Unix 下传统使用的最常见的命令行语法和语义。如果您不熟悉这些约定,请阅读本节以熟悉它们。
术语¶
- 参数
在命令行上输入的字符串,并由 shell 传递给
execl()或execv()。在 Python 中,参数是sys.argv[1:]的元素(sys.argv[0]是正在执行的程序的名称)。Unix shell 也使用术语“词”。有时希望替换除
sys.argv[1:]之外的参数列表,因此您应该将“参数”理解为“sys.argv[1:]的元素,或作为sys.argv[1:]替代提供的其他列表的元素”。- 选项
用于提供额外信息以指导或自定义程序执行的参数。选项有许多不同的语法;传统的 Unix 语法是连字符(“-”)后跟单个字母,例如
-x或-F。此外,传统的 Unix 语法允许将多个选项合并到单个参数中,例如-x -F等效于-xF。GNU 项目引入了--后跟一系列用连字符分隔的单词,例如--file或--dry-run。这是optparse提供的两种选项语法。世界上还见过一些其他选项语法,包括
连字符后跟几个字母,例如
-pf(这与将多个选项合并到单个参数中不同)连字符后跟整个单词,例如
-file(从技术上讲,这等效于前面的语法,但它们通常不会出现在同一个程序中)加号后跟单个字母、几个字母或单词,例如
+f、+rgb斜杠后跟字母、几个字母或单词,例如
/f、/file
这些选项语法不受
optparse支持,将来也不会支持。这是故意的:前三个在任何环境中都是非标准的,而最后一个只有在您专门针对 Windows 或某些遗留平台(例如 VMS、MS-DOS)时才有意义。- 选项参数
紧跟在选项后面的参数,与该选项密切相关,并在解析该选项时从参数列表中消耗。使用
optparse时,选项参数可以与选项位于不同的参数中-f foo --file foo
或者包含在同一个参数中
-ffoo --file=foo
通常,给定的选项要么接受参数,要么不接受参数。许多人想要一个“可选选项参数”功能,这意味着某些选项会在看到参数时接受参数,而不会看到参数时则不会接受参数。这有点争议,因为它使解析变得模棱两可:如果
-a接受可选参数,而-b是另一个完全不同的选项,我们如何解释-ab?由于这种歧义,optparse不支持此功能。- 位置参数
在解析选项后,参数列表中剩下的东西,即在解析选项及其参数并将其从参数列表中删除后剩下的东西。
- 必需选项
必须在命令行上提供的选项;请注意,短语“必需选项”在英语中自相矛盾。
optparse不会阻止您实现必需选项,但也不会在这方面提供太多帮助。
例如,考虑以下假设的命令行
prog -v --report report.txt foo bar
-v 和 --report 都是选项。假设 --report 接受一个参数,则 report.txt 是一个选项参数。 foo 和 bar 是位置参数。
选项的作用是什么?¶
选项用于提供额外的信息来调整或定制程序的执行。如果还不清楚,选项通常是可选的。程序应该能够在没有任何选项的情况下正常运行。(从 Unix 或 GNU 工具集中随机选择一个程序。它可以在没有任何选项的情况下运行并仍然有意义吗?主要的例外是 find、tar 和 dd——它们都是变异的怪胎,因其非标准语法和令人困惑的界面而受到批评。)
许多人希望他们的程序具有“必需选项”。想想看。如果它是必需的,那么它就不是可选的!如果您的程序需要一些信息才能成功运行,那么这就是位置参数的用途。
作为良好命令行界面设计的示例,请考虑简单的 cp 实用程序,用于复制文件。在不提供目标和至少一个源的情况下尝试复制文件没有多大意义。因此,如果您在没有参数的情况下运行 cp,它将失败。但是,它具有灵活、实用的语法,不需要任何选项。
cp SOURCE DEST
cp SOURCE ... DEST-DIR
您只需使用它就可以走得很远。大多数 cp 实现提供了一堆选项来精确调整文件复制的方式:您可以保留模式和修改时间,避免跟踪符号链接,在覆盖现有文件之前询问,等等。但这并没有分散 cp 的核心任务,即复制一个文件到另一个文件,或将多个文件复制到另一个目录。
位置参数的作用是什么?¶
位置参数用于您的程序绝对、肯定需要运行的那些信息。
一个好的用户界面应该尽可能少地包含绝对要求。如果您的程序需要 17 个不同的信息才能成功运行,那么您从用户那里获取这些信息的方式并不重要——大多数人会在成功运行程序之前放弃并离开。这适用于命令行、配置文件或 GUI:如果您对用户提出如此多的要求,他们中的大多数人会简单地放弃。
简而言之,尝试最大限度地减少用户绝对需要提供的信息量——尽可能使用合理的默认值。当然,您还想让您的程序具有合理的灵活性。这就是选项的用途。同样,它们是配置文件中的条目、GUI 的“首选项”对话框中的小部件还是命令行选项并不重要——您实现的选项越多,您的程序就越灵活,其实现就越复杂。当然,过度的灵活性也有缺点;过多的选项会让用户不知所措,并使您的代码更难维护。
教程¶
虽然 optparse 非常灵活且功能强大,但在大多数情况下也很容易使用。本节介绍任何基于 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将是用户提供的文件名,或者如果用户没有提供该选项,则为Noneargs,解析选项后剩余的位置参数列表
本教程部分仅介绍四个最重要的选项属性:action、type、dest(目标)和 help。其中,action 是最基本的。
了解选项操作¶
操作告诉 optparse 在命令行上遇到选项时该怎么做。optparse 中硬编码了一组固定的操作;添加新操作是本节 扩展 optparse 中介绍的更高级主题。大多数操作告诉 optparse 在某个变量中存储一个值——例如,从命令行获取一个字符串并将其存储在 options 的属性中。
如果您没有指定选项操作,optparse 默认使用 store。
store 操作¶
最常见的选项操作是 store,它告诉 optparse 获取下一个参数(或当前参数的剩余部分),确保它属于正确的类型,并将其存储到您选择的目的地。
例如
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 支持的其他一些选项类型是 int 和 float。这是一个期望整数参数的选项
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 还包含内置的 complex 类型。添加类型在 扩展 optparse 部分介绍。
处理布尔值(标志)选项¶
标志选项——当看到特定选项时将变量设置为真或假——非常常见。 optparse 使用两个独立的操作来支持它们,store_true 和 store_false。例如,您可能有一个 verbose 标志,它通过 -v 打开,通过 -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。
其他操作¶
optparse 支持的其他一些操作是
"store_const"存储一个常量值,通过
Option.const预先设置"append"将此选项的参数追加到列表中
"count"将计数器增加 1
"callback"调用指定的函数
默认值¶
以上所有示例都涉及在看到某些命令行选项时设置一些变量(“目标”。如果从未看到这些选项,会发生什么?由于我们没有提供任何默认值,因此它们都被设置为 None。这通常没问题,但有时您需要更多控制。 optparse 允许您为每个目标提供一个默认值,该值在解析命令行之前分配。
首先,考虑 verbose/quiet 示例。如果我们希望 optparse 将 verbose 设置为 True,除非看到 -q,那么我们可以这样做
parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")
由于默认值适用于目标而不是任何特定选项,并且这两个选项恰好具有相同的目标,因此这与以下完全等效
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:为任何特定目标提供的最后一个默认值是有效的。
指定默认值的更清晰方法是 set_defaults() 方法,该方法是 OptionParser 的方法,您可以在调用 parse_args() 之前随时调用它
parser.set_defaults(verbose=True)
parser.add_option(...)
(options, args) = parser.parse_args()
如前所述,为给定选项目标指定的最后一个值是有效的。为了清晰起见,请尝试使用其中一种方法或另一种方法来设置默认值,而不是同时使用两种方法。
生成帮助¶
optparse 自动生成帮助和使用文本的功能对于创建用户友好的命令行界面非常有用。您只需为每个选项提供一个 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会负责换行并使帮助输出看起来更好。需要值的选项会在其自动生成的帮助信息中表明这一点,例如,对于“mode”选项
-m MODE, --mode=MODE
这里,“MODE”被称为元变量:它代表用户需要提供给
-m/--mode的参数。默认情况下,optparse会将目标变量名转换为大写并将其用作元变量。有时,这不是您想要的——例如,--filename选项明确设置了metavar="FILE",从而导致自动生成的选项描述如下-f FILE, --filename=FILE
这不仅是为了节省空间,而且很重要:手动编写的帮助文本使用元变量
FILE来提示用户,半正式语法-f FILE和非正式语义描述“将输出写入 FILE”之间存在联系。这是一种简单但有效的方法,可以使您的帮助文本更清晰,对最终用户更有用。具有默认值的选项可以在帮助字符串中包含
%default——optparse会用选项的默认值的str()替换它。如果选项没有默认值(或默认值为None),则%default会扩展为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。
打印版本字符串¶
类似于简短的使用字符串,optparse 也可以为您的程序打印版本字符串。您必须将字符串作为 version 参数提供给 OptionParser
parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")
%prog 的扩展方式与在 usage 中相同。除此之外,version 可以包含任何您喜欢的內容。当您提供它时,optparse 会自动将 --version 选项添加到您的解析器中。如果它在命令行中遇到此选项,它将扩展您的 version 字符串(通过替换 %prog),将其打印到标准输出,并退出。
例如,如果您的脚本名为 /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()¶
与
print_version()相同,但返回版本字符串而不是打印它。
optparse 如何处理错误¶
有两种主要的错误类型,optparse 需要担心:程序员错误和用户错误。程序员错误通常是 OptionParser.add_option() 的错误调用,例如无效的选项字符串、未知的选项属性、缺少的选项属性等。这些错误以通常的方式处理:引发异常(optparse.OptionError 或 TypeError),并让程序崩溃。
处理用户错误要重要得多,因为无论您的代码多么稳定,它们都一定会发生。 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() 方法。
综合起来¶
以下是基于 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()
参考指南¶
创建解析器¶
使用 optparse 的第一步是创建一个 OptionParser 实例。
- class optparse.OptionParser(...)¶
OptionParser 构造函数没有必需参数,但有一些可选的关键字参数。您应该始终将它们作为关键字参数传递,即不要依赖参数声明的顺序。
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。子字符串%prog的扩展方式与usage相同。conflict_handler(默认值:"error")指定在将具有冲突选项字符串的选项添加到解析器时要执行的操作;请参阅部分 选项之间的冲突。
description(默认值:None)一段文字,简要概述您的程序。
optparse会重新格式化这段文字以适合当前终端宽度,并在用户请求帮助时打印它(在usage之后,但在选项列表之前)。formatter(默认值:一个新的IndentedHelpFormatter)一个 optparse.HelpFormatter 实例,将用于打印帮助文本。
optparse为此目的提供了两个具体类:IndentedHelpFormatter 和 TitledHelpFormatter。add_help_option(默认值:True)如果为真,
optparse会将一个帮助选项(具有选项字符串-h和--help)添加到解析器。prog在
usage和version中扩展%prog时要使用的字符串,而不是os.path.basename(sys.argv[0])。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() 是一个用于创建 Option 实例的工厂函数;目前它是 Option 构造函数的别名。未来版本的 optparse 可能会将 Option 分成多个类,而 make_option() 将选择正确的类进行实例化。不要直接实例化 Option。)
定义选项¶
每个 Option 实例代表一组同义的命令行选项字符串,例如 -f 和 --file。您可以指定任意数量的短选项或长选项字符串,但您必须至少指定一个总选项字符串。
创建 Option 实例的规范方法是使用 OptionParser 的 add_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"存储一个常量值,通过
Option.const预先设置"store_true"存储
True"store_false"存储
False"append"将此选项的参数追加到列表中
"append_const"将一个常数值追加到列表中,该常数值通过
Option.const预先设置"count"将计数器增加 1
"callback"调用指定的函数
"help"打印一个使用信息,其中包含所有选项及其文档
(如果您没有提供 action,则默认值为
"store"。对于此 action,您也可以提供type和dest选项属性;请参阅 标准选项操作。)
如您所见,大多数操作都涉及在某个地方存储或更新值。 optparse 始终为此创建一个特殊对象,通常称为 options,它是 optparse.Values 的实例。
- class optparse.Values¶
一个对象,它将解析后的参数名称和值作为属性保存。通常通过调用
OptionParser.parse_args()来创建,并且可以通过传递给OptionParser.parse_args()的 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"
选项属性¶
- class optparse.Option¶
单个命令行参数,具有通过关键字传递给构造函数的各种属性。通常使用
OptionParser.add_option()而不是直接创建,并且可以通过OptionParser的 option_class 参数传递的自定义类来覆盖。
以下选项属性可以作为关键字参数传递给 OptionParser.add_option()。如果您传递了与特定选项无关的选项属性,或者没有传递必需的选项属性,optparse 将引发 OptionError。
- Option.dest¶
(默认:从选项字符串派生)
如果选项的操作意味着在某个地方写入或修改值,则这会告诉
optparse在哪里写入它:dest指定了optparse在解析命令行时构建的options对象的属性。
- Option.default¶
如果命令行上没有看到该选项,则用于该选项目标的值。另请参见
OptionParser.set_defaults()。
- Option.const¶
对于存储常数值的操作,要存储的常数值。
- Option.choices¶
对于类型为
"choice"的选项,用户可以选择的一系列字符串。
标准选项操作¶
各种选项操作都有略微不同的要求和效果。大多数操作都有几个相关的选项属性,您可以指定这些属性来指导 optparse 的行为;一些操作有必需的属性,您必须为使用该操作的任何选项指定这些属性。
"store"[相关:type,dest,nargs,choices]该选项必须后跟一个参数,该参数将根据
type转换为值,并存储在dest中。如果nargs> 1,将从命令行中消费多个参数;所有参数都将根据type转换为值,并作为元组存储到dest中。请参见 标准选项类型 部分。如果提供了
choices(字符串列表或元组),则类型默认为"choice"。如果未提供
type,则默认为"string"。如果未提供
dest,则optparse从第一个长选项字符串(例如,--foo-bar意味着foo_bar)推导出目标。如果没有长选项字符串,则optparse从第一个短选项字符串(例如,-f意味着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将设置options.f = "foo.txt" options.point = (1.0, -3.5, 4.0) options.f = "bar.txt"
"store_const"[必需: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")
如果看到
--noisy,optparse将设置options.verbose = 2
"store_true"[相关:dest]"store_const"的一个特例,它将True存储到dest。"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]该选项必须后跟一个参数,该参数将追加到
dest中的列表。如果未提供dest的默认值,则当optparse首次在命令行上遇到此选项时,会自动创建一个空列表。如果nargs> 1,将消费多个参数,并将长度为nargs的元组追加到dest。type和dest的默认值与"store"操作相同。示例
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"[必需:const;相关:dest]类似于
"store_const",但值const会附加到dest;与"append"一样,dest默认值为None,并且在第一次遇到该选项时会自动创建一个空列表。"count"[相关:dest]增加存储在
dest中的整数。如果没有提供默认值,则在第一次增加之前,dest将被设置为零。示例
parser.add_option("-v", action="count", dest="verbosity")
第一次在命令行中看到
-v时,optparse会执行以下操作: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会自动将help选项添加到所有 OptionParsers,因此您通常不需要创建它。示例
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,它将向 stdout 打印类似以下帮助消息(假设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
打印帮助消息后,
optparse会使用sys.exit(0)终止您的进程。"version"打印传递给 OptionParser 的版本号到 stdout 并退出。版本号实际上是由 OptionParser 的
print_version()方法格式化和打印的。通常仅在将version参数传递给 OptionParser 构造函数时才相关。与help选项一样,您很少会创建version选项,因为optparse会在需要时自动添加它们。
标准选项类型¶
optparse 有五个内置选项类型:"string"、"int"、"choice"、"float" 和 "complex"。如果您需要添加新的选项类型,请参见部分 扩展 optparse。
字符串选项的参数不会以任何方式进行检查或转换:命令行上的文本将按原样存储在目标中(或传递给回调)。
整数参数(类型 "int")将按以下方式解析:
如果数字以
0x开头,则将其解析为十六进制数如果数字以
0开头,则将其解析为八进制数如果数字以
0b开头,则将其解析为二进制数否则,该数字将被解析为十进制数。
转换是通过调用 int() 并使用适当的基数(2、8、10 或 16)来完成的。如果转换失败,optparse 也会失败,但会显示更实用的错误信息。
"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与作为 values 传入的相同对象,或由
optparse创建的optparse.Values实例args在所有选项都处理完后剩下的位置参数
最常见的用法是不提供任何关键字参数。如果您提供 values,它将使用重复的 setattr() 调用(大致对应于存储到选项目标的每个选项参数)进行修改,并由 parse_args() 返回。
如果 parse_args() 在参数列表中遇到任何错误,它将调用 OptionParser 的 error() 方法,并显示适当的最终用户错误信息。这最终将使用退出状态 2(命令行错误的传统 Unix 退出状态)终止您的进程。
查询和操作您的选项解析器¶
选项解析器的默认行为可以稍微定制,您也可以查看您的选项解析器并了解其内容。OptionParser 提供了一些方法来帮助您。
- OptionParser.disable_interspersed_args()¶
将解析设置为在第一个非选项处停止。例如,如果
-a和-b都是不带参数的简单选项,optparse通常接受以下语法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 子类,其中包含一些标准选项,则尤其如此。)
每次添加选项时,optparse 会检查与现有选项的冲突。如果发现任何冲突,它将调用当前的冲突处理机制。您可以在构造函数中设置冲突处理机制
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")
此时,optparse 检测到之前添加的选项已经在使用 -n 选项字符串。由于 conflict_handler 是 "resolve",它通过从早期选项的选项字符串列表中删除 -n 来解决这种情况。现在 --dry-run 是用户激活该选项的唯一方法。如果用户请求帮助,帮助消息将反映这一点
Options:
--dry-run do no harm
...
-n, --noisy be noisy
可以逐渐减少之前添加的选项的选项字符串,直到没有剩余的选项字符串,用户无法从命令行调用该选项。在这种情况下,optparse 将完全删除该选项,因此它不会显示在帮助文本或其他任何地方。继续我们现有的 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
清理¶
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()是设置选项默认值的推荐方法,因为多个选项可以共享相同的目标。例如,如果多个“模式”选项都设置了相同的目标,那么其中任何一个都可以设置默认值,最后一个设置的默认值将生效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")
选项回调¶
当 optparse 的内置操作和类型不足以满足您的需求时,您有两个选择:扩展 optparse 或定义一个回调选项。扩展 optparse 更通用,但对于许多简单情况来说过于复杂。通常情况下,一个简单的回调就足够了。
定义回调选项有两个步骤
使用
"callback"操作定义选项本身编写回调;这是一个函数(或方法),它至少接受四个参数,如下所述
定义回调选项¶
与往常一样,定义回调选项的最简单方法是使用 OptionParser.add_option() 方法。除了 action 之外,您必须指定的唯一选项属性是 callback,即要调用的函数
parser.add_option("-c", action="callback", callback=my_callback)
callback 是一个函数(或其他可调用对象),因此在创建此回调选项时,您必须已经定义了 my_callback()。在这个简单的例子中,optparse 甚至不知道 -c 是否接受任何参数,这通常意味着该选项不接受任何参数——命令行上仅仅存在 -c 就足够了。然而,在某些情况下,您可能希望您的回调函数消耗任意数量的命令行参数。这就是编写回调函数变得棘手的地方;这将在本节后面介绍。
optparse 始终将四个特定参数传递给您的回调函数,并且只有当您通过 callback_args 和 callback_kwargs 指定它们时,它才会传递其他参数。因此,最小的回调函数签名是
def my_callback(option, opt, value, parser):
回调函数的四个参数将在下面描述。
在定义回调选项时,您可以提供几个其他选项属性
type具有其通常的含义:与
"store"或"append"操作一样,它指示optparse消耗一个参数并将其转换为type。但是,optparse不会将转换后的值存储在任何地方,而是将其传递给您的回调函数。nargs也具有其通常的含义:如果它被提供并且 > 1,
optparse将消耗nargs个参数,每个参数都必须可转换为type。然后它将转换后的值的元组传递给您的回调函数。callback_args传递给回调函数的额外位置参数的元组
callback_kwargs传递给回调函数的额外关键字参数的字典
回调函数的调用方式¶
所有回调函数的调用方式如下
func(option, opt_str, value, parser, *args, **kwargs)
其中
选项是调用回调函数的 Option 实例
opt_str是命令行上看到的触发回调函数的选项字符串。(如果使用了缩写的长选项,则
opt_str将是完整的规范选项字符串——例如,如果用户在命令行上输入--foo作为--foobar的缩写,那么opt_str将是"--foobar"。)value是命令行上看到的此选项的参数。
optparse只有在设置了type时才会期望一个参数;value的类型将是选项类型所隐含的类型。如果此选项的type为None(不期望参数),那么value将为None。如果nargs> 1,则value将是适当类型的值的元组。parser是驱动整个过程的 OptionParser 实例,主要有用是因为您可以通过其实例属性访问一些其他有趣的数据
parser.largs当前的剩余参数列表,即已被消耗但既不是选项也不是选项参数的参数。您可以随意修改
parser.largs,例如通过向其中添加更多参数。(此列表将成为args,即parse_args()的第二个返回值。)parser.rargs当前的剩余参数列表,即删除了
opt_str和value(如果适用)后,只有它们后面的参数仍然存在。您可以随意修改parser.rargs,例如通过消耗更多参数。parser.values默认存储选项值的(optparse.OptionValues 的实例)对象。这使回调函数可以使用与
optparse的其余部分相同的机制来存储选项值;您无需处理全局变量或闭包。您还可以访问或修改命令行上已经遇到的任何选项的值。
args是通过
callback_args选项属性提供的任意位置参数的元组。kwargs是通过
callback_kwargs提供的任意关键字参数的字典。
在回调函数中引发错误¶
如果选项或其参数存在任何问题,回调函数应引发 OptionValueError。 optparse 会捕获此错误并终止程序,将您提供的错误消息打印到 stderr。您的消息应清晰、简洁、准确,并提及有问题的选项。否则,用户将很难弄清楚他们做错了什么。
回调函数示例 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:固定参数¶
当您定义接受固定数量参数的回调选项时,事情会变得稍微有趣一些。指定回调选项接受参数类似于定义 "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 个参数并将它们转换为整数;您只需要存储它们即可。(或者其他任何操作;显然您不需要为此示例使用回调函数。)
回调函数示例 6:可变参数¶
当您想要一个可以接受可变数量参数的选项时,事情就会变得复杂。在这种情况下,您必须编写一个回调函数,因为 optparse 没有提供任何内置功能来实现这一点。而且您必须处理传统 Unix 命令行解析中的一些复杂问题,这些问题通常由 optparse 为您处理。特别是,回调函数应该实现对裸 -- 和 - 参数的传统规则
无论是
--还是-都可以作为选项参数裸
--(如果不是某个选项的参数):停止命令行处理并丢弃--裸
-(如果不是某个选项的参数):停止命令行处理,但保留-(将其追加到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)
扩展 optparse¶
由于 optparse 解释命令行选项的两个主要控制因素是每个选项的操作和类型,因此扩展最有可能的方向是添加新的操作和新的类型。
添加新类型¶
要添加新类型,您需要定义自己的 optparse 的 Option 类的子类。此类有两个属性定义了 optparse 的类型:TYPES 和 TYPE_CHECKER。
- Option.TYPE_CHECKER¶
一个字典,将类型名称映射到类型检查函数。类型检查函数具有以下签名
def check_mytype(option, opt, value)
其中
option是一个Option实例,opt是一个选项字符串(例如,-f),value是来自命令行的字符串,必须对其进行检查并转换为所需的类型。check_mytype()应该返回一个假设类型为mytype的对象。类型检查函数返回的值最终将出现在由OptionParser.parse_args()返回的 OptionValues 实例中,或者作为value参数传递给回调函数。如果您的类型检查函数遇到任何问题,它应该引发
OptionValueError。OptionValueError接受一个字符串参数,该参数将原样传递给OptionParser的error()方法,该方法依次在程序名称和字符串"error:"之前添加前缀,并将所有内容打印到 stderr,然后终止进程。
这里有一个简单的示例,演示了如何将 "complex" 选项类型添加到命令行中以解析 Python 风格的复数。(这比以前更愚蠢,因为 optparse 1.3 添加了对复数的内置支持,但没关系。)
首先,必要的导入
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
(如果我们没有对 copy() 的 Option.TYPE_CHECKER 进行复制,我们将最终修改 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)
添加新操作¶
添加新操作有点棘手,因为您必须了解 optparse 对操作进行了几种分类
- “store” 操作
导致
optparse将值存储到当前 OptionValues 实例的属性中的操作;这些选项需要在 Option 构造函数中提供dest属性。- “typed” 操作
从命令行获取值并期望其为特定类型;或者更确切地说,是一个可以转换为特定类型的字符串。这些选项需要在 Option 构造函数中提供
type属性。
这些是重叠的集合:一些默认的“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¶
始终需要类型的操作(即其选项始终需要值的)也会在此处列出。这唯一的意义在于
optparse会将默认类型"string"分配给没有显式类型且其操作列在ALWAYS_TYPED_ACTIONS中的选项。
为了实际实现新的操作,您必须覆盖 Option 的 take_action() 方法,并添加一个识别您的操作的 case。
例如,让我们添加一个 "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_ACTIONS中,也在TYPED_ACTIONS中。为了确保
optparse将默认类型"string"分配给"extend"操作,我们也将在ALWAYS_TYPED_ACTIONS中放置"extend"操作。MyOption.take_action()只实现了这个新的操作,并将控制权传递回Option.take_action()以执行标准的optparse操作。values是 optparse_parser.Values 类的实例,它提供了非常有用的ensure_value()方法。ensure_value()本质上是getattr()具有安全阀;它被调用为values.ensure_value(attr, value)
如果
values的attr属性不存在或为None,则 ensure_value() 首先将其设置为value,然后返回value。这对于像"extend"、"append"和"count"这样的操作非常有用,它们都在变量中累积数据,并期望该变量为特定类型(前两个为列表,最后一个为整数)。使用ensure_value()意味着使用您的操作的脚本不必担心为相关选项目标设置默认值;它们可以将默认值保留为None,而ensure_value()会在需要时确保正确设置。
异常¶
- exception optparse.OptionConflictError¶
如果将冲突的选项添加到
OptionParser中,则会引发此异常。
- exception optparse.OptionValueError¶
如果在命令行上遇到无效的选项值,则会引发此异常。
- exception optparse.BadOptionError¶
如果在命令行上传递了无效的选项,则会引发此异常。
- exception optparse.AmbiguousOptionError¶
如果在命令行上传递了模棱两可的选项,则会引发此异常。