简体   繁体   English

Python argparse可选子参数

[英]Python argparse optional sub-arguments

I'd like to have an argument to my program that has some required parameters along with some optional parameters. 我想为我的程序提供一个参数,该参数具有一些必需的参数以及一些可选的参数。 Something like this: 像这样:

[--print text [color [size]]

so you could pass it any of these: 因此您可以通过以下任何一项:

mycommand --print hello
mycommand --print hello blue
mycommand --print hello red 12

There could be multiple of these so it has to be a single add_argument. 这些可能有多个,因此必须是一个add_argument。 For example: 例如:

[--print text [color]] [--output filename [overwrite]]

I can achieve arguments that are close to what I want: 我可以实现接近我想要的参数:

>>> 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 ...]]

but not quite. 但不完全是 Is there any way to do this with argparse? 有什么办法可以用argparse吗? I know I could make them all nargs="*" but then --help would not list the names of the optional arguments. 我知道我可以将它们全部设置为nargs="*"但是--help不会列出可选参数的名称。 If I pass nargs="*" and a tuple for metavar, argparse throws an exception. 如果我传递nargs="*"和metavar的元组,则argparse会引发异常。

How about 怎么样

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)

Then you get something like this: 然后,您将得到如下内容:

$ ./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')

Reading the source code (start in take_action ), I believe what you want is impossible. 阅读源代码 (从take_action开始),我相信您想要的是不可能的。 All argument parsing and passing to actions is done based on nargs, and nargs is either a number, OPTIONAL ("?"), ZERO_OR_MORE ("*"), ONE_OR_MORE ("+"), PARSER , or REMAINDER . 所有参数解析和传递给操作均基于nargs进行,nargs是一个数字, OPTIONAL (“?”), ZERO_OR_MORE (“ *”), ONE_OR_MORE (“ +”), PARSERREMAINDER This must be determined before the Action object (which handles the input) even sees what it's getting, so it can't dynamically figure out nargs . 必须在Action对象(处理输入)甚至看到它得到的东西之前确定它,因此它不能动态地找出nargs

I think you'll need to live with a workaround. 我认为您将需要一个变通方法。 I would maybe have --foo-x x , --foo-y y , and --foo-z z , and perhaps also --foo xyz . 我可能会有--foo-x x ,-- --foo-y y--foo-z z ,也许还有--foo xyz

According to Devin Jeanpierre's answer, it seems that using '+' (one or more) instead of '*' would do what you are trying to achieve. 根据Devin Jeanpierre的回答,似乎使用'+'(一个或多个)而不是'*'将完成您要实现的目标。 (PS: I would've just commented in his answer if I had enough points) (PS:如果我有足够的观点,我会在他的回答中发表评论)

that will work for single arg: 适用于单个arg:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM