问题描述
我想将无限数量的选项传递给click CLI.我也不知道选项名称.我通过使用名为conf
的选项来解决此问题.它接受假定代表JSON对象的字符串.
I want to pass an unlimited number of options to a click CLI. I don't know Option names either. I'm getting around this issue by using an option named conf
. It accepts a string that is assumed to represent a JSON object.
我所做的:
@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
推荐答案
您可以钩住解析器并使它知道从命令行给出的每个选项,例如:
You can hook the parser and make it aware of each option given from the command line like:
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()
装饰器,例如:
Using the Custom Class:
To use the custom class, just pass the class to the click.command()
decorator like:
@click.command(cls=AcceptAllCommand)
def my_command(**kwargs):
...
这是如何工作的?
之所以有用,是因为click是一个设计良好的OO框架. @click.command()
装饰器通常会实例化click.Command
对象,但允许使用cls
参数覆盖此行为.因此,在我们自己的类中从click.Command
继承并超越所需的方法是相对容易的事情.
How does this work?
This works because click is a well designed OO framework. The @click.command()
decorator usually instantiates a click.Command
object but allows this behavior to be over-ridden with the cls
parameter. So it is a relatively easy matter to inherit from click.Command
in our own class and over ride the desired methods.
在这种情况下,我们将覆盖make_parser()
并将选项字典替换为我们自己的dict
类.在我们的dict
中,我们重写了__contains__()
魔术方法,在其中,我们为解析器填充了一个与要查找的名称匹配的选项(如果该名称尚不存在的话).
In this case, we override make_parser()
and replace the option dicts with a dict
class of our own. In our dict
we override the __contains__()
magic method, and in it we populate the parser with an option matching the name that is being looked for, if that name does not already exist.
@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'}
这篇关于如何使用Click CLI框架接受不确定数量的选项(以及如何查询其名称/值)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!