我在我的简单Python程序中使用 docopt :
#!/usr/bin/env python
"""
Farmers market
Usage:
farmersmarket.py buy -i <item> -q <quantity> [<quantity>] [-p <price>] [-dvh]
farmersmarket.py -d | --debug
farmersmarket.py -v | --version
farmersmarket.py -h | --help
Options:
-i --item Item.
-q --quantity Quantity.
-p --price Price.
-d --debug Show debug messages.
-h --help Show this screen.
-v --version Show version.
"""
from docopt import docopt
print docopt(__doc__)
如果我跑:
farmersmarket.py buy --item eggs --quantity 100 115 --price 0.25
预期的行为是以0.25的价格在价值100和115之间购买随机数量的鸡蛋。至少在解释参数时,这没有问题。换句话说, docopt 可以按预期获得所有内容:
{'--debug': False,
'--help': False,
'--item': True,
'--price': True,
'--quantity': True,
'--version': False,
'<item>': 'eggs',
'<price>': '0.25',
'<quantity>': ['100', '115'],
'buy': True}
然而,有时我不想购买随机数量的鸡蛋,但需要特定数量的鸡蛋。在这种情况下,--quantity
选项只接受一个参数:
farmersmarket.py buy --item eggs --quantity 471 --price 0.25
但由于 docopt 将--price 0.25
解释为--quantity
的重复元素并失去<price>
的值,因此失败了:
{'--debug': False,
'--help': False,
'--item': True,
'--price': True,
'--quantity': True,
'--version': False,
'<item>': 'eggs',
'<price>': None,
'<quantity>': ['471', '0.25'],
'buy': True}
如何在重复元素后获得其他选项?
答案 0 :(得分:11)
实际上,您忘记将<price>
参数添加到Options:
描述部分;以下代码:
#!/usr/bin/env python
"""
Farmers market
Usage:
farmersmarket.py buy -i <item> -q <quantity> [<quantity>] [-p <price>] [-dvh]
farmersmarket.py -d | --debug
farmersmarket.py -v | --version
farmersmarket.py -h | --help
Options:
-i --item Item.
-q --quantity Quantity.
-p --price <price> Price.
-d --debug Show debug messages.
-h --help Show this screen.
-v --version Show version.
"""
from docopt import docopt
print docopt(__doc__)
按预期工作:
% farmersmarket.py buy --item eggs --quantity 100 --price 0.25
{'--debug': False,
'--help': False,
'--item': True,
'--price': '0.25',
'--quantity': True,
'--version': False,
'<item>': 'eggs',
'<quantity>': ['100'],
'buy': True}
编辑:
但实际上,你试图实现的是错误的。如果你看一下你将看到的解析参数:
'--quantity': True,
[…]
'<quantity>': ['100'],
表示您定义了一个布尔--quantity
参数和一个位置quantity
参数。两者都无关......结果如下:
buy --items eggs --quantity --price 0.25 100 2
给出了结果:
'--quantity': True,
[…]
'<quantity>': ['100','2'],
这不是你想要的......所以让我们回到你想要的东西:你说你想要一个带有两个值的参数来定义一个min和一个可选的max。但我很遗憾地告诉您,在geptopt
,argparse
而不是docopt
中,这个确切的规则是不可能的。
解析完成后,解决方案将始终涉及一些逻辑,或者您需要更改解析参数的方式。所以我可以看到四个选项:
Farmers market
Usage:
farmersmarket.py buy -i <item> -m <min> [-M <max>] [-p <price>] [-dvh]
farmersmarket.py -d | --debug
farmersmarket.py -v | --version
farmersmarket.py -h | --help
Options:
-i --item <item> Item.
-m --min <min> Minimal quantity.
-M --max <min> Maximal quantity.
-p --price <price> Price.
-d --debug Show debug messages.
-h --help Show this screen.
-v --version Show version.
这里,最简单但我认为最好的解决方案是使用两个不同的选项来设置最大和最小边界。这是解析器处理{1,2}
个参数的唯一方法,并且是应该实现它的方式。
让你真正拥有列表参数的最接近的方法是使用语法实际“玩”:
Farmers market
Usage:
farmersmarket.py buy -i <item> -q <quantity> [-p <price>] [-dvh]
farmersmarket.py -d | --debug
farmersmarket.py -v | --version
farmersmarket.py -h | --help
Options:
-i --item <item> Item.
-q --quantity <quantity> Quantity: min[,max]
-p --price <price> Price.
-d --debug Show debug messages.
-h --help Show this screen.
-v --version Show version.
然后你可以使用:
% farmersmarket.py buy --items eggs -q 100,2 --price 0.25
并通过if len(docopt(__doc__)['--quantity'].split(',')) == 2: qmin, qmax = docopt(__doc__)['--quantity'].split(',')
获取最小值和最大值。
最后,你的最后一个解决方案是仅使用位置参数:
Farmers market
Usage:
farmersmarket.py buy <item> <min_qty> [<max_qty>] [-p <price>] [-dvh]
farmersmarket.py -d | --debug
farmersmarket.py -v | --version
farmersmarket.py -h | --help
Options:
<item> Item.
<min_qty> Minimum quantity
<max_qty> Maximum quantity
-p --price <price> Price.
-d --debug Show debug messages.
-h --help Show this screen.
-v --version Show version.
然后在你打电话时起作用:
% farmersmarket.py buy eggs 100 2 -p 0.25
但是看起来你想要获得一个参数列表,并且使用命令行选项实现这一目的的唯一方法是重复选项-q 1 -q 2 -q 3…
。要告诉docopt你想要什么,你需要在选项的参数后添加省略号:
Farmers market
Usage:
farmersmarket.py buy -i <item> -q <quantity>... [-p <price>] [-dvh]
farmersmarket.py -d | --debug
farmersmarket.py -v | --version
farmersmarket.py -h | --help
Options:
-i --item <item> Item.
-q --quantity <quantity>... Quantity (-q min -q max)
-p --price <price> Price.
-d --debug Show debug messages.
-h --help Show this screen.
-v --version Show version.
然后你可以打电话:
% farmersmarket.py buy --items eggs -q 100 -q 2 --price 0.25
但是,你必须检查len(docopt(__doc__)['--quantity']) < 2
(因为解析器会强制你至少给出一个)。但是,你必须在描述中清楚地说明你的意思,并给出一两个例子。
最后,我建议你使用除选项列表之外的其他三个选项之一,因为它们可以让你更清楚地调用你的程序。