2011-03-10 47 views
9

我想有一个参数,我的程序,有一些可选的参数以及一些必要的参数。事情是这样的:的Python argparse可选的分论点

[--print text [color [size]] 

,所以你可以通过它的部分包括:

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

可能有多个,这些所以它是一个单一的add_argument。例如:

[--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会抛出异常。

回答

5

阅读source code(从take_action开始),我相信你想要的是不可能的。所有参数解析和传递到动作是基于nargs完成的,而nargs是数字OPTIONAL(“?”),ZERO_OR_MORE(“*”),ONE_OR_MORE(“+”),PARSERREMAINDER。这必须是确定的行动对象(句柄输入)甚至认为它是越来越之前,所以它不能动态地计算出nargs

我认为你需要忍受一个解决办法。我想也许有--foo-x x--foo-y y--foo-z z,或许也是--foo x y z

+1

感谢。这太糟糕了。 – jterrace 2011-03-11 03:44:33

7

如何

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) 

然后你得到这样的事情:

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

但是,您只能一次指定一个子分析器,这样做是否适用于多个分析器。 – jterrace 2011-12-14 15:07:58

+0

你可以举一个多个例子吗?我的例子归结为可选的位置参数,它们都是nargs ='?',所以取决于你需要做什么,它可以在没有子分析器的情况下完成。或多个subparsers .. :) – CNeo 2011-12-16 15:36:18

+0

我在我的OP的例子:我的命令 - 打印你好红12 - 输出文件名覆盖 – jterrace 2011-12-16 16:55:16

0

,将单ARG工作:

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

根据德文Jeanpierre的答案,似乎使用'+'(一个或多个)而不是'*'会做你想要达到的目标。 (PS:我刚刚在他的回答评论,如果我有足够的点数)

+0

不要忘记 - 他也不想有超过三个参数。如果你将这个内容加入到你的文章中,那么你可以发表一个独立的答案(当然,如果你认为让皮埃尔的想法。) – Alex 2017-08-22 16:15:49