命令中的可选参数,单击

时间:2017-05-18 19:17:21

标签: python python-click

我正在尝试使用Click进行CLI解析不太标准的事情,它只能部分工作:

  • 主CLI有多个子命令(下面的示例'显示''检查')
  • 这些命令可能都有可选参数,但参数在它们之前不在
  • 之后
  • 我决定在小组"上面"处理这个论点。它并传递上下文中的值

样品:

import click

@click.group()
@click.argument('hostname', required=False)
@click.pass_context
def cli(ctx, hostname=None):
    """"""
    ctx.obj = hostname
    click.echo("cli: hostname={}".format(hostname))

@cli.command()
@click.pass_obj
def check(hostname):
    click.echo("check: hostname={}".format(hostname))

@cli.command()
@click.pass_obj
def show(hostname):
    click.echo("check: hostname={}".format(hostname))

if __name__ == '__main__':
    cli()

主机名的部分有效:

> pipenv run python cli.py  localhost check
cli: hostname=localhost
check: hostname=localhost
> pipenv run python cli.py  localhost show
cli: hostname=localhost
check: hostname=localhost

但没有主机名的部分不是:

> pipenv run python cli.py show
Usage: cli.py [OPTIONS] [HOSTNAME] COMMAND [ARGS]...

Error: Missing command.

有人对我应该开始研究的方向有所了解吗?

1 个答案:

答案 0 :(得分:5)

这可以通过覆盖click.Group参数解析器来完成,如:

自定义类:

class MyGroup(click.Group):
    def parse_args(self, ctx, args):
        if args[0] in self.commands:
            if len(args) == 1 or args[1] not in self.commands:
                args.insert(0, '')
        super(MyGroup, self).parse_args(ctx, args)

使用自定义类:

然后使用自定义组,将其作为cls参数传递给group装饰器,如:

@click.group(cls=MyGroup)
@click.argument('hostname', required=False)
@click.pass_context
def cli(ctx, hostname=None):
    ....

如何吗

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

在这种情况下,我们超越click.Group.parse_args()并且如果第一个参数与命令匹配而第二个参数不匹配,那么我们插入一个空字符串作为第一个参数。这会将所有内容放回解析器所期望的位置。