argparse可选的位置参数和子分析器参数
我有一个python脚本,它接受一个可选的位置参数,并有几个子命令。 其中一些子命令需要位置参数,有些则不需要。 我尝试使用不需要位置参数的子命令时出现了问题。 考虑以下测试文件:
import argparse
argp = argparse.ArgumentParser()
argp.add_argument('inputfile', type=str, nargs='?',
help='input file to process')
argp.add_argument('--main_opt1', type=str,
help='global option')
subp = argp.add_subparsers(title='subcommands',
dest='parser_name',
help='additional help',
metavar="<command>")
tmpp = subp.add_parser('command1', help='command1 help')
tmpp.add_argument('pos_arg1', type=str,
help='positional argument')
print repr(argp.parse_args())
当我尝试使用带有第一个参数的子命令command1
,一切都很顺利。
macbook-pro:~ jmlopez$ python pytest.py filename command1 otherarg
Namespace(inputfile='filename', main_opt1=None, parser_name='command1', pos_arg1='otherarg')
但是现在让我们假设command1
不需要第一个位置参数。
macbook-pro:~ jmlopez$ python pytest.py command1 otherarg
usage: pytest.py [-h] [--main_opt1 MAIN_OPT1] [inputfile] <command> ...
pytest.py: error: argument <command>: invalid choice: 'otherarg' (choose from 'command1')
我莫名其妙地被期待inputfile
被设置为None
。 有没有什么办法argparse
可以预测, command1
实际上是一个子命令,因此inputfile
应设置为无?
为了argp
子分析器说法看起来就像另一个位置,即需要选择(在subparsers的名称)。 此外argp
一无所知pos_arg1
。 这是在tmpp
的参数列表中。
当argp
看到filename command1 otherarg
, filename
和command1
满足其2个positionals。 otherarg
然后传递给tmpp
。
用command1 otherarg
,再2个字符串,2个argp
定位。 command
被分配给inputfile
。 没有逻辑可以回溯,并说command1
更适合subcommands
,或者`tmpp'需要其中一个字符串。
您可以将第一个位置更改为可选的--inputfile
。
或者你可以inputfile
的另一个位置tmpp
。 如果一些子分析器需要它,请考虑使用parents
。
和你一样, argparse
不是一个聪明的人,并且不能“提前思考”或“回溯”。 如果它看起来很聪明,那是因为它使用re
匹配模式来处理nargs
值(例如?,*,+)。
编辑
“欺骗”的一种方法是认为第一个位置作为子分析器在其后面插入一个可选项。 使用command1 -b xxx otherarg
, -b xxx
分解位置字符串列表,因此只有command1
与inputfile
和subcommands
匹配。
p=argparse.ArgumentParser()
p.add_argument('file',nargs='?',default='foo')
sp = p.add_subparsers(dest='cmd')
spp = sp.add_parser('cmd1')
spp.add_argument('subfile')
spp.add_argument('-b')
p.parse_args('cmd1 -b x three'.split())
# Namespace(b='x', cmd='cmd1', file='foo', subfile='three')
这里的问题是argparse
如何用变量nargs
处理nargs
。 第二个位置是一个子分析器的事实并不重要。 尽管argparse
允许以任意顺序设置可变长度的位置,但它如何处理它们可能会造成混淆。 如果只有一个这样的位置,那么预测什么是argparse
会更容易,并且最终会发生。
你需要告诉解析器第一个参数是不同的类型。 尝试添加标志选项和默认None
值,如下所示:
argp.add_argument('-i','--inputfile', type=str, nargs='?',
help='input file to process',default=None)
现在,您需要在输入文件参数前添加-i
,但它会正常工作。
macbook-pro:~ jmlopez$ python pytest.py -i filename command1 otherarg
Namespace(inputfile='filename', main_opt1=None, parser_name='command1', pos_arg1='otherarg')
和
macbook-pro:~ jmlopez$ python pytest.py command1 otherarg
Namespace(inputfile=None, main_opt1=None, parser_name='command1', pos_arg1='otherarg')
链接地址: http://www.djcxy.com/p/28555.html
上一篇: argparse optional positional argument and subparsers arguments