如何使用单击CLI框架接受无限数量的选项(以及如何查询它们的名称/值)?



我想将无限数量的选项传递给单击 CLI。我也不知道选项名称。我通过使用名为conf的选项来解决此问题。它接受假定表示 JSON 对象的字符串。

我做了什么:

@click.command()
@click.option('--conf', type=str)
def dummy(conf):
click.echo('dummy param {}'.format(conf))

我如何使用它:

>python main.py dummy --conf='{"foo": "bar", "fizz": "buzz"}'

我想做什么:

@click.command()
#some magic stuff
def dummy(**kwargs):
click.echo('dummy param {}'.format(**kwargs))

我想如何使用它:

>python main.py dummy --foo=bar --fizz=buzz

您可以挂钩解析器并使其知道从命令行给出的每个选项,例如:

自定义命令类:

import click
class AcceptAllCommand(click.Command):
def make_parser(self, ctx):
"""Hook 'make_parser' and allow the opt dict to find any option"""
parser = super(AcceptAllCommand, self).make_parser(ctx)
command = self
class AcceptAllDict(dict):
def __contains__(self, item):
"""If the parser does no know this option, add it"""
if not super(AcceptAllDict, self).__contains__(item):
# create an option name
name = item.lstrip('-')
# add the option to our command
click.option(item)(command)
# get the option instance from the command
option = command.params[-1]
# add the option instance to the parser
parser.add_option(
[item], name.replace('-', '_'), obj=option)
return True
# set the parser options to our dict
parser._short_opt = AcceptAllDict(parser._short_opt)
parser._long_opt = AcceptAllDict(parser._long_opt)
return parser

使用自定义类:

要使用自定义类,只需将类传递给click.command()装饰器,如下所示:

@click.command(cls=AcceptAllCommand)
def my_command(**kwargs):
...

这是如何工作的?

这是有效的,因为单击是一个设计良好的OO框架。@click.command()修饰器通常实例化click.Command对象,但允许使用cls参数覆盖此行为。因此,从我们自己的类中的click.Command继承并覆盖所需的方法相对容易。

在这种情况下,我们覆盖make_parser()并将选项字典替换为我们自己的dict类。 在我们的dict中,我们覆盖了__contains__()魔术方法,并在其中使用与正在查找的名称匹配的选项填充解析器(如果该名称尚不存在(。

测试代码:

@click.command(cls=AcceptAllCommand)
def dummy(**kwargs):
click.echo('dummy param: {}'.format(kwargs))
if __name__ == "__main__":
import time
cmd = '--foo=bar --fizz=buzz'
print('Click Version: {}'.format(click.__version__))
print('Python Version: {}'.format(sys.version))
print('-----------')
print('> ' + cmd)
time.sleep(0.1)
dummy(cmd.split())

结果:

Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> --foo=bar --fizz=buzz
dummy param: {'foo': 'bar', 'fizz': 'buzz'}        

最新更新