单击命令中的可选参数

问题描述 投票:0回答:2

我正在尝试使用 Click 完成一些对于 CLI 解析来说不是很标准的事情,但它只能部分工作:

  • 主 CLI 有多个子命令(在下面的示例中“show”和“check”)
  • 这两个命令可能有可选参数,但参数位于它们之前而不是之后
  • 我决定在其“上方”组中处理该参数,并在上下文中传递值

样品:

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.

有人知道我应该开始研究的方向吗?

python python-click
2个回答
19
投票

这可以通过覆盖

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
是一个设计良好的面向对象框架。
@click.group()
装饰器通常会实例化
click.Group
对象,但允许使用
cls
参数覆盖此行为。 因此,在我们自己的类中继承
click.Group
并覆盖所需的方法是一件相对容易的事情。

在这种情况下,我们会覆盖

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


0
投票

我正在尝试解决这个问题..

我的做法有两种。

  1. 将该值默认为空字符串。我更喜欢给它一个我正在做的事情的值,因为我有代码读取该变量。
@click.argument(
    "myarg", default="",
)
  1. 另一种说法是不需要。
@click.argument(
    "myarg", required=False,
)
© www.soinside.com 2019 - 2024. All rights reserved.