我必须用这样的命令行参数创建一个解析器
python function.py -v 1 name1 -d abc xyz foo bar name2 -i 3 -p abc xyz
我这样做了:
import argparse
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('-v', type=int, help='number')
subparsers = parser.add_subparsers(help='sub-command help', dest="command")
parser_a = subparsers.add_parser('name1', help="name1 help")
parser_a.add_argument("-d", help="list", nargs="+")
parser_b = subparsers.add_parser('name2', help="name2 help")
parser_b.add_argument("-p", help="list2", nargs='+')
parser_b.add_argument("-i", help="number inside name2", type=int)
当我运行时:
parser.parse_args('-v 1 name1 -d abc xyz foo bar name2 -i 3 -p abc xyz'.split())
结果是:
usage: PROG [-h] [-v V] {name1,name2} ...
PROG: error: unrecognized arguments: -i 3 -p abc xyz
运行时:
parser.parse_args('-v 1 name1 -d abc xyz foo bar name2'.split())
结果如下:
Namespace(command='name1', d=['abc', 'xyz', 'foo', 'bar', 'name2'], v=1)
我希望它是这样的:
Namespace(command='name1', d=['abc', 'xyz', 'foo', 'bar'], command='name2', p=['abc', 'xyz'], i=3, v=1)
我该怎么做?
答案 0 :(得分:0)
当你注意到
In [24]: parser.parse_args('-v 1 name1 -d abc xyz foo bar name2'.split())
Out[24]: Namespace(command='name1', d=['abc', 'xyz', 'foo', 'bar', 'name2'], v=1)
name2
被视为parser_a
-d
参数
其他'-i 3 -p abc xyz'不被接受,因为-i
被理解为可选标志。
有效地你正在运行:
In [28]: parser_a.parse_args('-d abc xyz foo bar name3 -i 3 -p abc xyz'.split())
usage: PROG name1 [-h] [-d D [D ...]]
PROG name1: error: unrecognized arguments: -i 3 -p abc xyz
主解析器有一个位置参数,可接受2个选项,name1
和name2
。当遇到name1
时,它会将其余参数传递给parser_a
。
净效果是argparse
只接受一个子命令。
在之前的SO问题中,我已经讨论了一些方法。侧边栏找到了一个:
Python argparser repeat subparse
(这可能足以将此问题标记为重复)。
如果我向parser_a
添加位置;并使用--
分隔bar
和name2
(意思是,以下所有内容都是位置)
In [32]: parser_a.add_argument('extra',nargs='*')
Out[32]: _StoreAction(option_strings=[], dest='extra', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [33]: parser.parse_args('-v 1 name1 -d abc xyz foo bar -- name2 -i 3 -p abc xyz'.split())
Out[33]: Namespace(command='name1', d=['abc', 'xyz', 'foo', 'bar'], extra=['name2', '-i', '3', '-p', 'abc', 'xyz'], v=1)
然后我可以将extra
字符串(减去name2
)传递给parser_b
:
In [34]: args=_
In [36]: parser_b.parse_args(args.extra[1:])
Out[36]: Namespace(i=3, p=['abc', 'xyz'])
不可否认,这是一个令人费解的解决方案,但几年前我提出的解决方案并没有好多少。希望它有助于澄清正在发生的事情。
您是否真的需要一次调用2个子命令。如果可以的话,argparse
会更简单:
python function.py -v 1 name1 -d abc xyz foo bar
python function.py -v 1 name2 -i 3 -p abc xyz
换句话说,调用脚本两次。如果对function.py
的每次调用都执行独立的自包含操作,那么这很容易 - 在共享文件或数据库中包含的两个调用之间存在任何连接。这就是经常使用子命令的方式。尝试在一次调用中放置多个子命令不会节省输入。
答案 1 :(得分:0)
我认为你做错了什么。 首先,您应该传递位置参数,然后传递关键字参数,例如
python myapp.py arg1 arg2 --kwarg1=1 --kwarg2 val1 --kwarg2 val2