Python 使用nargs='+';

Python 使用nargs='+';,python,argparse,Python,Argparse,我必须用这样的命令行参数创建一个解析器 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(hel

我必须用这样的命令行参数创建一个解析器

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)
我该怎么做?

正如你所说

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
被视为
解析器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
主解析器有一个位置参数,它接受两个选项,
name1
name2
。当遇到
name1
时,它将其余参数传递给
解析器a

净效果是,
argparse
只接受一个子命令

我在前面的SO问题中讨论了一些解决方法。侧边栏找到了一个:

(这可能非常适合将此问题标记为重复问题)


如果我向
解析器添加一个位置;并使用
--
分隔
名称2
(意思是,后面的内容都是位置)

然后我可以将
额外的
字符串(减去
name2
)传递给
parser\b

In [34]: args=_
In [36]: parser_b.parse_args(args.extra[1:])
Out[36]: Namespace(i=3, p=['abc', 'xyz'])
诚然,这是一个复杂的解决方案,但我几年前提出的方案并没有好多少。希望这有助于澄清正在发生的事情


您真的需要一次调用两个子命令吗
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
的每个调用都执行一个独立的自包含操作,那么这很容易实现——两个调用之间的任何连接都体现在共享文件或数据库中。这就是经常使用子命令的方式。试图在一个调用中放入多个子命令并不能节省键入时间。

我认为您做错了什么。 首先应该传递位置参数,然后传递关键字参数,例如

python myapp.py arg1 arg2 --kwarg1=1 --kwarg2 val1 --kwarg2 val2 

两个问题:一次只能调用一个子parser(作为主脚本的第一个位置参数),即使可以调用多个子parser,也无法判断
-d
选项的参数的结束位置。
name2
是位置参数还是
-d
的参数?name2应该是位置参数。如果这种方法不可行,还有其他方法吗?您可以使用这种解决方法:argparse更灵活;它可以处理混合位置和标记位置。但在本例中,当引入自己的解析约束时,他也使用了
subparsers
。@hpaulj我的意思是,在本例中,subparsers是过度杀伤力的。实际上,原始命令是:
python function.py-v 1 name1 name2
其中name1,name2是要运行的子模块。现在我希望它们也接受命令行参数。
python myapp.py arg1 arg2 --kwarg1=1 --kwarg2 val1 --kwarg2 val2