【问题标题】:Python argparse optional sub-argumentsPython argparse 可选子参数
【发布时间】:2017-11-28 04:06:59
【问题描述】:

我想为我的程序添加一个参数,其中包含一些必需参数和一些可选参数。像这样的:

[--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="*" 和元组元组,argparse 会引发异常。

【问题讨论】:

    标签: python argparse


    【解决方案1】:

    怎么样

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

    【讨论】:

    • 但是你一次只能指定一个子解析器,这样做对多个不起作用。
    • 你能举个例子吗?我的例子归结为可选的位置参数,都是 nargs='?',所以根据你需要做什么,它可以在没有子解析器的情况下完成。或多个子解析器.. :)
    • 我的 OP 中有示例:mycommand --print hello red 12 --output filename overwrite
    • 抱歉,我可能应该更清楚地阅读这个问题。您可以使用nargs='+'nargs='*' 模拟您所追求的,这已经和您一样接近了。 metavar 确实可以取一个元组,但只能定义两个名称(不是三个)。你也可以覆盖帮助,比如parser.add_argument('--print', nargs='+', metavar=('text', 'color'), help='--print text [color [size]]')
    【解决方案2】:

    阅读source code(从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

    【讨论】:

      【解决方案3】:

      根据 Devin Jeanpierre 的回答,似乎使用 '+'(一个或多个)而不是 '*' 可以达到您想要达到的效果。 (PS:如果我有足够的积分,我会在他的回答中发表评论)

      【讨论】:

      • 别忘了——他也不想有超过三个参数。如果您将其合并到您的帖子中,那么您可以发布一个独立的答案(当然,如果您相信 Jean Pierre 的想法。)
      【解决方案4】:

      这将适用于单个 arg:

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

      【讨论】:

        猜你喜欢
        • 2019-11-17
        • 2019-07-12
        • 2017-01-14
        • 1970-01-01
        • 2019-01-28
        • 2017-01-15
        • 2021-05-06
        • 2020-08-24
        相关资源
        最近更新 更多