获取发送到 click.group() 子命令的参数

Get params sent to a subcommand of a click.group()

如果我有一个带有多个子命令的 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

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

自定义Class:

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

使用自定义 Class:

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

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

这是如何工作的?

之所以可行,是因为 click 是一个设计良好的 OO 框架。 @click.group() 装饰器通常实例化一个 click.Group 对象,但允许使用 cls 参数覆盖此行为。因此,在我们自己的 class 中继承 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