【问题标题】:Option with two arguments with docopt带有 docopt 的两个参数的选项
【发布时间】:2018-05-29 21:52:08
【问题描述】:

我想要一个带有两个参数的选项。 IE。希望能够使用

$ ./foo --path "old" "new"

或者我真正想要的是:

$ ./foo --path "old" "new" --path "old" "new"

但我不知道该怎么做? (其实我担心这可能是不可能的......)


我不想要,但很接近

我知道如何设置重复选项(见下文),但这真的不是我想要的。

#!/usr/bin/env python3
'''foo

Usage:
  foo [--path ARG]...

Options:
  --path=ARG  Repeating option.
'''

import docopt

args = docopt.docopt(__doc__)

print(args)

可以调用

$ ./foo --path "old" --path "new"

【问题讨论】:

    标签: python docopt


    【解决方案1】:

    这可以使用 docopt 轻松存档。

    语法:Usage: ./foo [--path <src> <dst>]...

    输入:./foo --path src1 dst1 --path src2 dst2

    代码:

    >>> from docopt import docopt
    >>> doc = "Usage: ./foo [--path <src> <dst>]..."
    >>> argv = "--path old1 new1 --path old2 new2".split()
    >>> args = docopt(doc, argv)
    

    结果:

    {
      "--path": 2, 
      "<dst>": [
        "dst1", 
        "dst2"
      ], 
      "<src>": [
        "src1", 
        "src2"
      ]
    }
    

    现在用它做点什么:

    >>> if bool(args["--path"]):
    >>>     n = 1 if args["--path"] is True else if args["--path"]
    >>>     for i in range(0, n)]:
    >>>         print("{}, {}".format(args["<old>"][i], args["<new>"][i]))
    src1, dst1
    src2, dst2
    

    要添加多个位置参数,要求路径选项和参数的顺序正确,括号为“( )”。

    Usage: ./foo [(--path <src> <dst>)]... <arg>...
    

    注意: docopt 不会引发SystemExit,以防用户混淆语法并输入./foo arg --path src dst,如果您使用带有多个参数的选项。您必须自己处理它或在它前面添加另一个(子)命令。

    Usage: ./foo [(--path <src> <dst>)]... bar <arg>...
    

    【讨论】:

    • 虽然它不是很健壮...从某种意义上说,它可以与位置参数混合在一起,没有任何警告。
    • 我遇到的唯一问题是,如果您混淆输入并在选项之间使用位置参数,docopt 不会引发SystemExit,但您可以检查解析的选项是否正确语法并自己提出。你能用位置参数说明你的问题吗?
    • 在这个例子中,当我输入./foo --path a b c 时,我认为应该引发一个错误(当然我可以手动这样做,仍然不是很成问题)。然而,Usage: ./foo [--path &lt;src&gt; &lt;dst&gt;]... &lt;arg&gt;... 变得更加成问题。在这种特殊情况下 ``./foo --path a b c` 无法解析,我认为应该在哪里解析?
    • 如果您想添加这样的位置参数,您应该要求 --path &lt;src&gt; 和 &lt;dst&gt; 以正确的顺序使用括号“( )”。我已经更新了我的问题。
    • 我引用的缺少的SystemExit 就是这种情况。这是错误的用法,因为选项应该在位置参数&lt;arg&gt; 之前。可以使用(子)命令来避免。
    【解决方案2】:

    docopt 无法做到这一点。

    项目所有者gives原因如下:

    因为在像prog --foo bar baz qux 这样的调用中,人们无法判断它是指prog --foo=bar baz qux 还是prog --foo=bar,baz qux 还是prog --foo=bar,baz,qux。

    我认为这很合理。

    我建议改用两个选项,可能是--from 和--to,或者--old-path 和--new-path。

    或者,您可以改用argparse,并设置nargs 选项(例如nargs=2)。

    【讨论】:

    • 谢谢!我知道 argparse 解决方案,但为了简单起见,我改用了 docopt。我想在我的实际问题中,我还可以要求用户指定 --path="/old/path;/new/path" 并有一个 --sep 选项。
    【解决方案3】:

    你可以使用点击库 http://click.pocoo.org/5/options/

    @click.command()
    @click.option('--path', '-m', multiple=True)
    def run(path):
        print('\n'.join(path))
    

    【讨论】:

    • 感谢您的点击建议。但是,您的解决方案似乎对我不起作用:/foo --path test test Usage: example [OPTIONS] Error: Got unexpected extra argument (test)
    • @TomdeGeus /foo -m test1 -m test2.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    • 2015-06-01
    • 1970-01-01
    • 2021-12-27
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多