我必须遗漏一些明显的东西。目标是使用argparse和第一个参数,第二个可选参数和任何其他剩余参数可选。
为了显示问题,我制作了两个测试解析器;它们之间的唯一区别是在一个中使用nargs = argparse.REMAINDER而在另一个中使用nargs ='*'。
def doParser1(argsin):
parser = argparse.ArgumentParser(description='Parser demo.')
parser.add_argument('req1', help='first required parameter')
parser.add_argument('--opt1', help='first optional parameter')
parser.add_argument('leftovers', nargs=argparse.REMAINDER,
help='all the other parameters')
argsout = parser.parse_args(args=argsin)
print argsout
return argsout
def doParser2(argsin):
parser = argparse.ArgumentParser(description='Parser demo.')
parser.add_argument('req1', help='first required parameter')
parser.add_argument('--opt1', help='first optional parameter')
parser.add_argument('leftovers', nargs='*',
help='all the other parameters')
argsout = parser.parse_args(args=argsin)
print argsout
return argsout
如果没有额外参数,则parser2可以正常工作。这是输入,后跟parser1和解析器1:
input: ['req1value', '--opt1', 'opt1value']
Namespace(leftovers=['--opt1', 'opt1value'], opt1=None, req1='req1value')
Namespace(leftovers=None, opt1='opt1value', req1='req1value')
如果有额外的参数,则在parser1中会遗漏opt1值,而解析器2会混淆:
input: ['req1value', '--opt1', 'opt1value', 'r1', 'r2']
Namespace(leftovers=['--opt1', 'opt1value', 'r1', 'r2'], opt1=None, req1='req1value')
usage: py-argparse.py [-h] [--opt1 OPT1]
[-leftovers [LEFTOVERS [LEFTOVERS ...]]]
req1
py-argparse.py: error: unrecognized arguments: r1 r2
预期输出应为:
Namespace(leftovers=['r1', 'r2'], opt1='opt1value', req1='req1value')
这似乎应该是一个简单的案例,这里的内容从我真正想要做的事情中简化了。我尝试过剩饭是可选的,添加了各种其他选项,但没有任何效果更好。
任何帮助都将不胜感激。
答案 0 :(得分:4)
--opt1
需要在“未命名”参数之前出现。你真正的测试用例应该是:
['--opt1', 'opt1value', 'req1value']
和
['--opt1', 'opt1value', 'req1value', 'r1', 'r2']
答案 1 :(得分:4)
您可以使用parse_known_args
:
import argparse
parser = argparse.ArgumentParser(description='Parser demo.')
parser.add_argument('req1', help='first required parameter')
parser.add_argument('--opt1', help='first optional parameter')
args, leftovers = parser.parse_known_args(['req1value', '--opt1', 'opt1value'])
print(args, leftovers)
# (Namespace(opt1='opt1value', req1='req1value'), [])
args, leftovers = parser.parse_known_args(['req1value', '--opt1', 'opt1value', 'r1', 'r2'])
print(args, leftovers)
# (Namespace(opt1='opt1value', req1='req1value'), ['r1', 'r2'])
答案 2 :(得分:2)
当一个或多个位置属于“零或更多”类型(? * REMAINDER
)时,位置和选项的混合是棘手的。简单的解决方案是不混合它们 - 首先给出选项,然后是所有的位置。
这是发生了什么:
input: ['req1value', '--opt1', 'opt1value']
Namespace(leftovers=['--opt1', 'opt1value'], opt1=None, req1='req1value')
由于req1value
字符串,解析器首先解析位置。 req1
想要1个字符串,leftovers
抓取其他所有内容,包括--opt1
。
Namespace(leftovers=None, opt1='opt1value', req1='req1value')
*
leftovers
对[]
感到满意,没有字符串,因此None
(实际上我得到[]
)。 --opt1
被解析为可选项。
input: ['req1value', '--opt1', 'opt1value', 'r1', 'r2']
...
py-argparse.py: error: unrecognized arguments: r1 r2
之前*
leftovers
设置为[]
。 -opt1
已处理完毕。但现在有2个字符串没有放置它们的地方。你打算让他们进入leftovers
,但那已经被使用了。如果leftovers
为+
,则会按照您的意图对其进行处理。
关键是当它试图解析第一个位置时,它也会尝试解析它可以的所有位置。在一个级别parse_args
正在生成re.match('(A)(A*)','AOA')
组('A', '')
。
有2个提议的补丁可以解决这个问题。一个人使用2步parse_known_args
来完成选项和位置的混合。这是optparse
用户可能期望的那种行为。
另一个补丁尝试延迟处理可以接受0
参数字符串http://bugs.python.org/issue15112的位置。