Python argparse 可选子参数

17 投票
4 回答
22296 浏览
提问于 2025-04-16 13:25

我想让我的程序接受一些必须的参数和一些可选的参数。类似这样:

[--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就会报错。

4 个回答

1

这个代码适用于单个参数:

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

这样怎么样

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')
8

阅读了源代码(从take_action开始),我觉得你想要的事情是不可能实现的。所有的参数解析和传递给动作的过程都是基于nargs来进行的,而nargs可以是一个数字、OPTIONAL("?")、ZERO_OR_MORE("*")、ONE_OR_MORE("+")、PARSER,或者REMAINDER。这些都必须在Action对象(负责处理输入的部分)看到输入之前就确定下来,所以它无法动态地确定nargs

我觉得你可能需要接受一个变通的方法。也许可以使用--foo-x x--foo-y y--foo-z z,还可以考虑--foo x y z

撰写回答