在python的OptionParser
中,如何指示它忽略提供给方法parse_args
的未定义选项?
e.g。
我只为--foo
个实例定义了选项OptionParser
,但我用parse_args
[ '--foo', '--bar' ]
编辑:
我不在乎它是否将它们从原始列表中过滤掉。我只想忽略未定义的选项。
我这样做的原因是因为我使用SCons的AddOption接口来添加自定义构建选项。但是,其中一些选项指导了目标的声明。因此,我需要在脚本中的不同点解析sys.argv,而无需访问所有选项。最后,顶级Scons OptionParser将捕获命令行中的所有未定义选项。
答案 0 :(得分:37)
这是使用简单的子类将{1}}的{{1}}添加到args
的未知参数的一种方法。
OptionParser.parse_args
这里有一个片段,表明它有效:
from optparse import (OptionParser,BadOptionError,AmbiguousOptionError)
class PassThroughOptionParser(OptionParser):
"""
An unknown option pass-through implementation of OptionParser.
When unknown arguments are encountered, bundle with largs and try again,
until rargs is depleted.
sys.exit(status) will still be called if a known argument is passed
incorrectly (e.g. missing arguments or bad argument types, etc.)
"""
def _process_args(self, largs, rargs, values):
while rargs:
try:
OptionParser._process_args(self,largs,rargs,values)
except (BadOptionError,AmbiguousOptionError), e:
largs.append(e.opt_str)
答案 1 :(得分:11)
默认情况下,无法修改传递未定义选项时引发的error()
调用行为。来自how optparse handles errors部分底部的文档:
如果optparse的默认错误处理行为不符合您的需求,您需要 子类OptionParser并覆盖其exit()和/或error()方法。
最简单的例子是:
class MyOptionParser(OptionParser):
def error(self, msg):
pass
这只会使对error()
的所有调用都不起作用。当然这并不理想,但我相信这说明了你需要做的事情。请记住来自error()
的文档字符串,您应该继续这样做:
打印包含'msg'的用法消息到stderr和 出口。 如果你在子类中重写它,它不应该返回 - 它 应退出或引发异常。
答案 2 :(得分:6)
Python 2.7(在询问此问题时不存在)现在提供argparse模块。您可以使用ArgumentParser.parse_known_args()
来完成此问题的目标。
答案 3 :(得分:3)
这是来自Optik distribution的pass_through.py
示例。
#!/usr/bin/env python
# "Pass-through" option parsing -- an OptionParser that ignores
# unknown options and lets them pile up in the leftover argument
# list. Useful for programs that pass unknown options through
# to a sub-program.
from optparse import OptionParser, BadOptionError
class PassThroughOptionParser(OptionParser):
def _process_long_opt(self, rargs, values):
try:
OptionParser._process_long_opt(self, rargs, values)
except BadOptionError, err:
self.largs.append(err.opt_str)
def _process_short_opts(self, rargs, values):
try:
OptionParser._process_short_opts(self, rargs, values)
except BadOptionError, err:
self.largs.append(err.opt_str)
def main():
parser = PassThroughOptionParser()
parser.add_option("-a", help="some option")
parser.add_option("-b", help="some other option")
parser.add_option("--other", action='store_true',
help="long option that takes no arg")
parser.add_option("--value",
help="long option that takes an arg")
(options, args) = parser.parse_args()
print "options:", options
print "args:", args
main()
答案 4 :(得分:1)
根据不同答案的评论中的每个synack的请求,我发布了一个解决方案的黑客,该解决方案在将输入传递给父OptionParser
之前对输入进行消毒:
import optparse
import re
import copy
import SCons
class NoErrOptionParser(optparse.OptionParser):
def __init__(self,*args,**kwargs):
self.valid_args_cre_list = []
optparse.OptionParser.__init__(self, *args, **kwargs)
def error(self,msg):
pass
def add_option(self,*args,**kwargs):
self.valid_args_cre_list.append(re.compile('^'+args[0]+'='))
optparse.OptionParser.add_option(self, *args, **kwargs)
def parse_args(self,*args,**kwargs):
# filter out invalid options
args_to_parse = args[0]
new_args_to_parse = []
for a in args_to_parse:
for cre in self.valid_args_cre_list:
if cre.match(a):
new_args_to_parse.append(a)
# nuke old values and insert the new
while len(args_to_parse) > 0:
args_to_parse.pop()
for a in new_args_to_parse:
args_to_parse.append(a)
return optparse.OptionParser.parse_args(self,*args,**kwargs)
def AddOption_and_get_NoErrOptionParser( *args, **kwargs):
apply( SCons.Script.AddOption, args, kwargs)
no_err_optparser = NoErrOptionParser(optparse.SUPPRESS_USAGE)
apply(no_err_optparser.add_option, args, kwargs)
return no_err_optpars