docopt 必需选项和带参数的选项

0 投票
1 回答
6414 浏览
提问于 2025-04-18 11:30

我刚接触docopt,正在尝试让一个小例子运行起来,但遇到了一些困难。目前我有两个小问题,希望能得到帮助,同时也欢迎对代码改进的建议。第一个问题是如何让程序强制要求使用--required这个选项。也就是说,如果没有这个必要的命令行选项,程序应该打印出文档说明。第二个问题是如何让程序接受参数(比如COMPUTER)来配合选项(比如--computer)。在终端中应该怎么输入这些内容,代码又应该怎么写呢?

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
my example program

Usage:
    docopt_example_1.py [--ipaddress=IPADDRESS] [--computer=COMPUTER]
    docopt_example_1.py --network <network>
    docopt_example_1.py (--required)
    docopt_example_1.py --notrequired
    docopt_example_1.py --version

Arguments:
    IPADDRESS               I.P. address
    COMPUTER                computer identification
    <network>               network identification

Options:
    -h, --help              Show this help message.
    --version               Show the version and exit.
    --required              option required for running
    --notrequired           option not required for running
    --ipaddress=IPADDRESS   I.P. address
    --computer=COMPUTER     computer identification
    --network=NETWORK       network identification
"""
from docopt import docopt

def main(options):
    print("----------")
    print("a printout of the command line options as parsed by docopt:")
    print(options)
    print("----------")
    if options["--notrequired"]:
        print("required option selected")
    if options["--computer"]:
        print("computer name: {computer}".format(computer=options["COMPUTER"]))
    if options["--network"]:
        print("computer name: {network}".format(network=options["<network>"]))
    else:
        print("no options")

if __name__ == "__main__":
    options = docopt(__doc__, version='1')
    main(options)

1 个回答

5

关于你的第一个问题,“所有元素默认都是必需的,如果不在括号中”。所有的使用行是平行的,这意味着输入只需要匹配其中任何一行,就会被认为是有效的。所以你需要把“必需参数”添加到所有的使用行中:

Usage:
    docopt_example_1.py --required [--notrequired] [--ipaddress=IPADDRESS] [--computer=COMPUTER]
    docopt_example_1.py --required [--notrequired] --network <network>
    docopt_example_1.py --version

在上面的例子中,如果你的输入不是“docopt_example_1.py --version”并且没有包含“--required”,那么运行时会打印出文档字符串。


关于第二个问题,可以通过使用选项名称来读取选项的参数:

print("computer name: {computer}".format(computer=options["--computer"]))
print("network name: {network}".format(network=options["--network"]))

另外,你可能需要注意官方站点的说明:

写成 --input ARG(而不是 --input=ARG)是模糊的,这意味着无法判断 ARG 是选项的参数还是位置参数。在使用模式中,只有在提供该选项的描述时,这将被解释为带参数的选项。否则,它将被解释为单独的选项和位置参数。

为了更好理解,如果你去掉这一行

--network=NETWORK       network identification

并且输入是 docopt_example_1.py --required [--notrequired] --network network_name,那么你将无法从 options['--network'] 中读取到“network_name”,而是需要使用 options['<network>']。因为在这种情况下,“network_name”被视为一个单独的位置参数。


顺便说一下,以下几行似乎有逻辑错误。else 只和最后一个 if 绑定在一起。我觉得这不是你想要的结果:

if options["--notrequired"]:
    print("required option selected")
if options["--computer"]:
    print("computer name: {computer}".format(computer=options["COMPUTER"]))
if options["--network"]:
    print("computer name: {network}".format(network=options["<network>"]))
else:
    print("no options")

参考资料:http://docopt.org/

撰写回答