36.1. optparse — 命令行选项解析器 — Python 文档
36.1. 选择解析 — 命令行选项解析器
源代码: :source:`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]
)。
36.1.1. 背景
optparse 被明确设计为鼓励使用简单的、传统的命令行界面创建程序。 为此,它仅支持在 Unix 下常规使用的最常见的命令行语法和语义。 如果您不熟悉这些约定,请阅读本节以熟悉它们。
36.1.1.1. 术语
- 争论
在命令行上输入的字符串,并由 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 不支持这些选项语法,并且永远不会支持。 这是故意的:前三个在任何环境中都是非标准的,最后一个只有在您专门针对 VMS、MS-DOS 和/或 Windows 时才有意义。
- 选项参数
跟随选项的参数与该选项密切相关,并在该选项存在时从参数列表中使用。 使用 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
是位置参数。
36.1.1.2. 什么是选项?
选项用于提供额外信息以调整或自定义程序的执行。 如果不清楚,选项通常是 optional。 程序应该能够在没有任何选项的情况下正常运行。 (从 Unix 或 GNU 工具集中随机选择一个程序。 它可以在没有任何选项的情况下运行并且仍然有意义吗? 主要的例外是 find
、tar
和 dd
——所有这些都是变异的古怪,因其非标准的语法和令人困惑的界面而受到了正确的批评。)
许多人希望他们的程序具有“必需的选项”。 想想看。 如果它是必需的,那么它是 不是可选的 ! 如果有一条信息是您的程序成功运行所绝对需要的,这就是位置参数的用途。
作为良好的命令行界面设计的一个例子,考虑用于复制文件的不起眼的 cp
实用程序。 在不提供目的地和至少一个来源的情况下尝试复制文件没有多大意义。 因此,如果不带参数运行 cp
会失败。 但是,它具有灵活、有用的语法,根本不需要任何选项:
cp SOURCE DEST
cp SOURCE ... DEST-DIR
你可以走得很远。 大多数 cp
实现提供了一系列选项来精确调整文件的复制方式:您可以保留模式和修改时间、避免跟随符号链接、在破坏现有文件之前询问等。 但这一切都不会分散 cp
的核心任务,即将一个文件复制到另一个文件,或将多个文件复制到另一个目录。
36.1.1.3. 什么是位置参数?
位置参数用于您的程序绝对需要运行的那些信息。
一个好的用户界面应该有尽可能少的绝对要求。 如果你的程序需要 17 条不同的信息才能成功运行,那么如何从用户那里获得这些信息并不重要——大多数人会在成功运行程序之前放弃并走开. 无论用户界面是命令行、配置文件还是 GUI,这都适用:如果您对用户提出那么多要求,他们中的大多数都会简单地放弃。
简而言之,尽量减少绝对需要用户提供的信息量——尽可能使用合理的默认值。 当然,您还希望使您的程序具有相当的灵活性。 这就是选项的用途。 同样,它们是配置文件中的条目、GUI 的“首选项”对话框中的小部件还是命令行选项都无关紧要——你实现的选项越多,你的程序就越灵活,也就越复杂它的实现变成了。 当然,太多的灵活性也有缺点。 太多的选项会让用户不知所措,并使您的代码更难维护。
36.1.2. 教程
虽然 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 遇到 option strings 并从中查找选项。
定义所有选项后,指示 optparse 解析程序的命令行:
(options, args) = parser.parse_args()
(如果您愿意,可以将自定义参数列表传递给 parse_args()
,但这很少需要:默认情况下它使用 sys.argv[1:]
。)
parse_args()
返回两个值:
options
,一个包含所有选项值的对象——例如 如果--file
采用单个字符串参数,则options.file
将是用户提供的文件名,如果用户未提供该选项,则None
args
,解析选项后剩余的位置参数列表
本教程部分仅涵盖四个最重要的选项属性:action、type、dest(目的地)和 help。 其中,action是最基本的。
36.1.2.1. 了解选项操作
Actions 告诉 optparse 当它在命令行上遇到一个选项时要做什么。 有一组固定的动作硬编码到 optparse 中; 添加新操作是 扩展 optparse 部分中介绍的高级主题。 大多数操作告诉 optparse 将值存储在某个变量中 - 例如,从命令行获取字符串并将其存储在 options
的属性中。
如果不指定选项操作,optparse 默认为 store
。
36.1.2.2. 店铺动作
最常见的选项动作是 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
。
让我们解析另一个假命令行。 这一次,我们将把 option 参数直接与 option 相对:由于 -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 部分中有介绍。
36.1.2.3. 处理布尔(标志)选项
标记选项——在看到特定选项时将变量设置为 true 或 false——非常常见。 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
。
36.1.2.4. 其他行为
optparse 支持的其他一些操作是:
"store_const"
- 存储一个常数值
"append"
- 将此选项的参数附加到列表中
"count"
- 将计数器加一
"callback"
- 调用指定的函数
这些内容在 参考指南 、参考指南和 选项回调 部分中有介绍。
36.1.2.5. 默认值
上述所有示例都涉及在看到某些命令行选项时设置一些变量(“目标”)。 如果从未见过这些选项会怎样? 由于我们没有提供任何默认值,它们都设置为 None
。 这通常很好,但有时您需要更多控制。 optparse 允许您为每个目标提供默认值,该值在解析命令行之前分配。
首先,考虑冗长/安静的例子。 如果我们想让 optparse 将 verbose
设置为 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)
考虑一下:
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()
和以前一样,为给定选项目标指定的最后一个值是最重要的值。 为清楚起见,请尝试使用一种方法或另一种设置默认值的方法,而不是同时使用两种方法。
36.1.2.6. 生成帮助
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 负责换行并使帮助输出看起来不错。
带值的选项在其自动生成的帮助消息中表明这一事实,例如 对于“模式”选项:
-m MODE, --mode=MODE
这里,“MODE”被称为元变量:它代表用户应该提供给
-m
/--mode
的参数。 默认情况下,optparse 将目标变量名称转换为大写并将其用于元变量。 有时,这不是您想要的——例如,--filename
选项显式设置metavar="FILE"
,从而导致此自动生成的选项描述:-f FILE, --filename=FILE
不过,这不仅仅是节省空间的重要原因:手动编写的帮助文本使用元变量
FILE
来提示用户,因为半正式语法-f FILE
和非正式语义描述“将输出写入文件”。 这是一种简单但有效的方法,可以使您的帮助文本更清晰,对最终用户更有用。具有默认值的选项可以在帮助字符串中包含
%default
- optparse 将替换为选项默认值的 str()。 如果选项没有默认值(或默认值为None
),则%default
扩展为none
。
36.1.2.6.1。 分组选项
在处理多个选项时,可以方便地将这些选项分组以获得更好的帮助输出。 一个 OptionParser 可以包含多个选项组,每个选项组可以包含多个选项。
使用类 OptionGroup 获得选项组:
- class optparse.OptionGroup(parser, title, description=None)
- 在哪里
- parser 是组将插入到的 OptionParser 实例
- 标题是组标题
- 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 的 OptionGroup(例如
'-o'
或'--option'
) 属于。 如果没有这样的 OptionGroup,则返回None
。
36.1.2.7. 打印版本字符串
与简要用法字符串类似,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() 相同,但返回版本字符串而不是打印它。
36.1.2.8. 如何选择解析处理错误
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()
方法。
36.1.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()
36.1.3. 参考指南
36.1.3.1. 创建解析器
使用 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
)- 如果为 true,optparse 将向解析器添加一个帮助选项(带有选项字符串
-h
和--help
)。 prog
- 在
usage
和version
中扩展%prog
而不是os.path.basename(sys.argv[0])
时使用的字符串。 epilog
(默认:None
)- 在选项帮助之后打印的一段帮助文本。
36.1.3.2. 填充解析器
有几种方法可以用选项填充解析器。 首选方法是使用 OptionParser.add_option(),如 Tutorial 部分所示。 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。)
36.1.3.3. 定义选项
每个 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"
存储一个常数值
"store_true"
存储真值
"store_false"
存储一个假值
"append"
将此选项的参数附加到列表中
"append_const"
将常量值附加到列表
"count"
将计数器加一
"callback"
调用指定的函数
"help"
打印使用消息,包括所有选项及其文档
(如果您不提供操作,则默认值为
"store"
。 对于此操作,您还可以提供 type 和 dest 选项属性; 请参阅 标准选项操作 。)
如您所见,大多数操作都涉及在某处存储或更新值。 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"
type 和 dest 选项属性几乎与 action 一样重要,但 action 是唯一对 有意义的属性所有 选项。
36.1.3.4. 选项属性
以下选项属性可以作为关键字参数传递给 OptionParser.add_option()。 如果您传递与特定选项无关的选项属性,或者无法传递必需的选项属性,则 optparse 引发 OptionError
。
- Option.type
(默认:
"string"
)此选项预期的参数类型(例如,
"string"
或"int"
); 可用的选项类型记录在 此处 。
- Option.dest
(默认:派生自选项字符串)
如果选项的操作意味着在某处写入或修改值,这会告诉 optparse 在哪里写入它: dest 命名 optparse 的
options
对象的属性 在解析命令行时构建。
- Option.default
- 如果在命令行上看不到该选项,则用于此选项目标的值。 另见 OptionParser.set_defaults()。
- 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
(默认:派生自选项字符串)
打印帮助文本时要使用的选项参数的替代品。 有关示例,请参阅 教程 部分。
36.1.3.5. 标准选项操作
各种选项操作都有略微不同的要求和效果。 大多数操作都有几个相关的选项属性,您可以指定这些属性来指导 optparse 的行为; 一些具有必需的属性,您必须为使用该操作的任何选项指定这些属性。
"store"
[相关:type、dest、nargs、选择]该选项必须后跟一个参数,该参数根据type转换为一个值并存储在dest中。 如果 nargs > 1,则命令行会消耗多个参数; all 将根据 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
,则会设置 optparseoptions.verbose = 2
"store_true"
[相关:dest]"store_const"
的特例,将真值存储到 dest。"store_false"
[相关:dest]类似于
"store_true"
,但存储一个假值。例子:
parser.add_option("--clobber", action="store_true", dest="clobber") parser.add_option("--no-clobber", action="store_false", dest="clobber")
"append"
[相关:type、dest、nargs、选择]该选项后必须跟一个参数,该参数附加到 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"
[必填:回调; 相关:type、nargs、callback_args、callback_kwargs]调用callback指定的函数,调用为
func(option, opt_str, value, parser, *args, **kwargs)
有关更多详细信息,请参阅 选项回调 部分。
"help"
打印当前选项解析器中所有选项的完整帮助消息。 帮助消息由传递给 OptionParser 的构造函数的
usage
字符串和传递给每个选项的 help 字符串构造而成。如果没有为选项提供 help 字符串,它仍将列在帮助消息中。 要完全省略选项,请使用特殊值
optparse.SUPPRESS_HELP
。optparse 会自动为所有 OptionParsers 添加一个 help 选项,因此您通常不需要创建一个。
例子:
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 会在需要时自动添加它们。
36.1.3.6. 标准选项类型
optparse 有五种内置选项类型:"string"
、"int"
、"choice"
、"float"
和 "complex"
。 如果您需要添加新的选项类型,请参阅 扩展 optparse 部分。
不以任何方式检查或转换字符串选项的参数:命令行上的文本按原样存储在目标中(或传递给回调)。
整数参数(类型 "int"
)解析如下:
- 如果数字以
0x
开头,则解析为十六进制数 - 如果数字以
0
开头,则解析为八进制数 - 如果数字以
0b
开头,则解析为二进制数 - 否则,数字被解析为十进制数
转换是通过使用适当的基数(2、8、10 或 16)调用 int() 来完成的。 如果失败,optparse 也会失败,尽管有更有用的错误消息。
"float"
和 "complex"
选项参数直接使用 float() 和 complex() 进行转换,具有类似的错误处理。
"choice"
选项是 "string"
选项的子类型。 choices 选项属性(字符串序列)定义了允许的选项参数集。 optparse.check_choice()
将用户提供的选项参数与此主列表进行比较,如果给出无效字符串,则引发 OptionValueError
。
36.1.3.7。 解析参数
创建和填充 OptionParser 的重点是调用它的 parse_args()
方法:
(options, args) = parser.parse_args(args=None, values=None)
其中输入参数是
args
- 要处理的参数列表(默认值:
sys.argv[1:]
) values
- 一个
optparse.Values
对象来存储选项参数(默认值:Values
的一个新实例)——如果你给一个现有的对象,选项默认值将不会被初始化
和返回值是
options
- 作为
values
传入的相同对象,或由 optparse 创建的 optparse.Values 实例 args
- 处理完所有选项后剩余的位置参数
最常见的用法是不提供关键字参数。 如果您提供 values
,它将被重复的 setattr() 调用修改(对于存储到选项目标的每个选项参数大约一个)并由 parse_args()
返回。
如果 parse_args()
在参数列表中遇到任何错误,它会调用 OptionParser 的 error()
方法并带有适当的最终用户错误消息。 这最终会以退出状态 2(命令行错误的传统 Unix 退出状态)终止您的进程。
36.1.3.8. 查询和操作您的选项解析器
选项解析器的默认行为可以稍微自定义,您还可以浏览您的选项解析器,看看那里有什么。 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 或
None
的选项实例。
- OptionParser.has_option(opt_str)
- 如果 OptionParser 具有带有选项字符串 opt_str 的选项(例如,
-q
或--verbose
),则返回 true。
- OptionParser.remove_option(opt_str)
- 如果 OptionParser 具有对应于 opt_str 的选项,则删除该选项。 如果该选项提供了任何其他选项字符串,则所有这些选项字符串都将无效。 如果在属于此 OptionParser 的任何选项中未出现 opt_str,则引发 ValueError。
36.1.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)
可用的冲突处理程序是:
"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
36.1.3.10。 清理
OptionParser 实例有几个循环引用。 这对于 Python 的垃圾收集器来说应该不是问题,但是您可能希望在完成后通过在 OptionParser 上调用 destroy()
来显式地中断循环引用。 这在可从 OptionParser 访问大型对象图的长时间运行的应用程序中特别有用。
36.1.3.11。 其他方法
OptionParser 支持其他几种公共方法:
- OptionParser.set_usage(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")
36.1.4. 期权回调
当 optparse 的内置操作和类型不足以满足您的需求时,您有两种选择:扩展 optparse 或定义回调选项。 扩展 optparse 更通用,但对于很多简单的情况来说太过分了。 通常,您只需要一个简单的回调即可。
定义回调选项有两个步骤:
- 使用
"callback"
操作定义选项本身 - 编写回调; 这是一个函数(或方法),它至少需要四个参数,如下所述
36.1.4.1. 定义回调选项
与往常一样,定义回调选项的最简单方法是使用 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
- 传递给回调的额外关键字参数字典
36.1.4.2. 如何调用回调
所有回调的调用方式如下:
func(option, opt_str, value, parser, *args, **kwargs)
在哪里
option
- 是调用回调的 Option 实例
opt_str
- 是在命令行上看到的触发回调的选项字符串。 (如果使用了缩写的 long 选项,
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 提供的任意关键字参数的字典。
36.1.4.3. 在回调中引发错误
如果选项或其参数有任何问题,回调函数应该引发 OptionValueError
。 optparse 捕获并终止程序,打印您提供给 stderr 的错误消息。 您的消息应该清晰、简洁、准确,并提及错误的选项。 否则,用户将很难弄清楚他们做错了什么。
36.1.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"
操作来做到这一点。
36.1.4.5. 回调示例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")
36.1.4.6。 回调示例 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')
36.1.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()
的定义留给读者作为练习。)
36.1.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 个参数并将它们转换为整数; 您所要做的就是存储它们。 (或者其他什么;显然你不需要这个例子的回调。)
36.1.4.9。 回调示例 6:可变参数
当您想要一个选项来接受可变数量的参数时,事情就会变得棘手。 对于这种情况,您必须编写回调,因为 optparse 不为其提供任何内置功能。 而且您必须处理 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)
36.1.5. 扩展选择解析
由于 optparse 如何解释命令行选项的两个主要控制因素是每个选项的动作和类型,因此最可能的扩展方向是添加新动作和新类型。
36.1.5.1。 添加新类型
要添加新类型,您需要定义自己的 optparse 的 Option
类的子类。 这个类有几个定义 optparse 类型的属性:TYPES 和 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
参数传递给回调。如果遇到任何问题,您的类型检查函数应该引发
OptionValueError
。OptionValueError
接受单个字符串参数,该参数按原样传递给 OptionParser 的error()
方法,该方法依次添加程序名称和字符串 [ X168X] 并在终止进程之前将所有内容打印到 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
(如果我们不制作 Option.TYPE_CHECKER 的 copy(),我们最终会修改 optparse 的 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)
36.1.5.2. 添加新动作
添加新动作有点棘手,因为您必须了解 optparse 对动作有几个分类:
- “存储”操作
- 导致 optparse 将值存储到当前 OptionValues 实例的属性的操作; 这些选项需要将 dest 属性提供给 Option 构造函数。
- “类型化”操作
- 从命令行获取值并期望它是某种类型的操作; 或者更确切地说,可以转换为某种类型的字符串。 这些选项需要 Option 构造函数的 type 属性。
这些是重叠的集合:一些默认的“存储”动作是 "store"
、"store_const"
、"append"
和 "count"
,而默认的“类型”动作是 [ X147X]、"append"
和 "callback"
。
当你添加一个动作时,你需要通过将它列在 Option 的以下类属性中的至少一个中来对其进行分类(都是字符串列表):
- Option.ACTIONS
- 所有操作都必须在 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
将导致一个列表
["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"
动作,我们也将"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)
如果
values
的attr
属性不存在或者是None
,则ensure_value()首先将其设置为value
,然后返回'value。 这对于像"extend"
、"append"
和"count"
这样的动作非常方便,所有这些动作都在一个变量中累积数据并期望该变量是某种类型(列表对于前两个,对于后者是一个整数)。 使用ensure_value()
意味着使用您的操作的脚本不必担心为相关选项目的地设置默认值; 他们可以将默认值保留为None
,而ensure_value()
会在需要时负责将其正确处理。