将params发送到click.group()

时间:2017-05-18 15:13:41

标签: python python-click

如果我有一个带有多个子命令的click.group(),有没有办法可以将命令行参数传递给组内的子命令?

我知道你可以通过context从小组向下走,我知道我可以使用在命令之前执行的callback函数,但我不知道是否有比使用callback更好的方法。

一个例子:

@click.group()
def cli():
    pass

@cli.command()
@click.argument('task')
@click.argument('task_id')
def sync(task, task_id):
    click.echo('Synching: {}'.format(task))

在此示例中,是否有任何方法可以在组方法中获取tasktask_id

1 个答案:

答案 0 :(得分:5)

这可以通过覆盖click.Group.invoke()方法来完成,例如:

自定义类:

class MyGroup(click.Group):
    def invoke(self, ctx):
        ctx.obj = tuple(ctx.args)
        super(MyGroup, self).invoke(ctx)

使用自定义类:

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

@click.group(cls=MyGroup)
@click.pass_context
def cli(ctx):
    args = ctx.obj
    ....

这是如何运作的?

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

在这种情况下,我们过度click.Group.invoke()并抓住参数并将它们放入ctx.obj字段。然后可以在cli()函数中访问它们。

测试代码:

import click

class MyGroup(click.Group):
    def invoke(self, ctx):
        ctx.obj = tuple(ctx.args)
        super(MyGroup, self).invoke(ctx)

@click.group(cls=MyGroup)
@click.pass_context
def cli(ctx):
    args = ctx.obj
    click.echo('cli: {} {}'.format(ctx.invoked_subcommand, ' '.join(args)))

@cli.command()
@click.argument('task')
@click.argument('task_id')
def sync(task, task_id):
    click.echo('Synching: {}'.format(task))

cli('sync task taskid'.split())

<强>结果:

cli: sync task taskid
Synching: task