Python argparse可选子参数

Python argparse可选子参数,python,argparse,Python,Argparse,我希望我的程序有一个参数,它有一些必需的参数和一些可选的参数。大概是这样的: [--print text [color [size]] $ ./test.py -h usage: test.py [-h] {print} ... positional arguments: {print} $ ./test.py print -h usage: test.py print [-h] text [color] [size] positional arguments: text c

我希望我的程序有一个参数,它有一些必需的参数和一些可选的参数。大概是这样的:

[--print text [color [size]]
$ ./test.py -h
usage: test.py [-h] {print} ...

positional arguments:
  {print}

$ ./test.py print -h
usage: test.py print [-h] text [color] [size]

positional arguments:
  text
  color
  size

$ ./test.py print text
Namespace(color=None, func=<function printText at 0x2a96150b90>, size=None, text='text')

$ ./test.py print text red
Namespace(color='red', func=<function printText at 0x2a96150b90>, size=None, text='text')

$ ./test.py print text red 12
Namespace(color='red', func=<function printText at 0x2a96150b90>, size=12, text='text')
因此,您可以通过以下任何一项:

mycommand --print hello
mycommand --print hello blue
mycommand --print hello red 12
可能有多个这样的参数,所以它必须是一个add_参数。例如:

[--print text [color]] [--output filename [overwrite]]
我可以实现接近我想要的论点:

>>> parser = argparse.ArgumentParser()
>>> act = parser.add_argument('--foo', nargs=3, metavar=('x','y','z'))
>>> act = parser.add_argument('--bar', nargs='?')
>>> act = parser.add_argument('--baz', nargs='*')
>>> parser.print_help()
usage: [-h] [--foo x y z] [--bar [BAR]] [--baz [BAZ [BAZ ...]]]

optional arguments:
  -h, --help            show this help message and exit
  --foo x y z
  --bar [BAR]
  --baz [BAZ [BAZ ...]]
但不完全如此。有没有办法用argparse实现这一点?我知道我可以让它们都
nargs=“*”
,但是--help不会列出可选参数的名称。如果我传递了
nargs=“*”
和metavar的元组,argparse就会抛出一个异常。

读取(从
开始采取行动),我相信您想要的是不可能的。所有参数解析和传递到操作的操作都是基于NARG完成的,NARG可以是一个数字、
可选的
(“?”)、
零或多个
(“*”)、
一个或多个
(“+”)、
解析器
余数
。这必须在操作对象(处理输入)看到它得到的东西之前确定,因此它不能动态地找出
nargs

我想你需要一个变通办法。我可能会有
--foo-x
--foo-y
,和
--foo-z z
,也许还有
--foo-x-y z

怎么样

def printText(args):
  print args

parser = argparse.ArgumentParser()
subparser = parser.add_subparsers()
printer = subparser.add_parser('print')
printer.add_argument('text')
printer.add_argument('color', nargs='?')
printer.add_argument('size', type=int, nargs='?')
printer.set_defaults(func=printText)

cmd = parser.parse_args()
cmd.func(cmd)
然后你会得到这样的结果:

[--print text [color [size]]
$ ./test.py -h
usage: test.py [-h] {print} ...

positional arguments:
  {print}

$ ./test.py print -h
usage: test.py print [-h] text [color] [size]

positional arguments:
  text
  color
  size

$ ./test.py print text
Namespace(color=None, func=<function printText at 0x2a96150b90>, size=None, text='text')

$ ./test.py print text red
Namespace(color='red', func=<function printText at 0x2a96150b90>, size=None, text='text')

$ ./test.py print text red 12
Namespace(color='red', func=<function printText at 0x2a96150b90>, size=12, text='text')
$。/test.py-h
用法:test.py[-h]{print}。。。
位置参数:
{print}
$./test.py打印-h
用法:test.py打印[-h]文本[颜色][大小]
位置参数:
文本
颜色
大小
$./test.py打印文本
命名空间(color=None,func=,size=None,text='text')
$./test.py打印文本红色
命名空间(color='red',func=,size=None,text='text')
$./test.py打印文本红色12
名称空间(color='red',func=,size=12,text='text')

适用于单个参数:

parser.add_argument('--write_google', nargs='?', const='Yes',
                    choices=['force', 'Yes'],
                    help="write local changes to google")

根据Devin Jeanpierre的回答,使用“+”(一个或多个)而不是“*”似乎可以实现您想要实现的目标。
(注:如果我有足够的分数,我会在他的回答中发表评论)

但是你一次只能指定一个子parser,这样做对多个子parser不起作用。你能举一个多个子parser的例子吗?我的示例可以归结为可选的位置参数,两者都是nargs=“?”,因此根据需要执行的操作,它可以在没有子parser的情况下完成。或多个子parser:)我的OP中有一个例子:mycommand——print hello red 12——output filename overwriteAppologies,我可能应该更清楚地阅读这个问题。。您可以使用
nargs='+'
nargs='*'
来模拟您所追求的,这已经和您所期望的一样接近了。metavar确实可以接受一个元组,但只能定义两个名称(不是三个)。您还可以覆盖帮助,例如
parser.add_参数('--print',nargs='+',metavar=('text',color'),help='--print text[color[size]])
别忘了--他也不希望有三个以上的参数。如果你将此纳入你的帖子,那么你可以发布一个独立的答案(当然,如果你相信让·皮埃尔的想法的话)