同时单击具有选项和命令的组

Click group with options and commands at the same time

我正在尝试创建具有以下行为的应用程序:

myapp - 将启动应用程序并执行 A

myapp "some argument" - 会做 B 事。B 事受参数 "some argument".

的影响

myapp command - 将启动具有功能 C 的 "command"(由装饰器 @cli.command 表示)。这将受到 click 必须提供的所有内容的影响,例如 @click.option.

注意,在我的应用程序中会有 更多命令 像 C.


我已尝试使用以下代码实现:

import click

class GroupWithOption(click.Group):
    def list_commands(self, ctx):
        return ['command']

    def get_command(self, ctx, cmd_name):
        if cmd_name == 'command':
            return command
        else:
            return do_b


@click.group(cls=GroupWithOption, invoke_without_command=True)
def main():
    print("Does A")

@main.command()
def command():
    print("Does C")

@main.command()
def do_b():
    print("Does B")


if __name__ == '__main__':
    main()

结果喜忧参半。首先,我可以很容易地调用 3 种不同的行为(或更多),但我无法弄清楚如何将参数传递给 B 命令。 我不喜欢这个解决方案。它似乎不是一个干净的解决方案。为了正常运行,它需要使用全局变量和一些讨厌的技巧。

你们知道更好的方法吗?如何完成这个?

一种方法是结合给出的两个答案 :

关键要素:

@click.group(cls=DefaultCommandGroup, invoke_without_command=True)
@click.pass_context
def main(ctx):
    if not ctx.invoked_subcommand:
        click.echo("Does A")

@main.command(default_command=True)
@click.argument('args', nargs=-1)
def default_cmd_with_args(args):
    click.echo("Does B: {}".format(args))

这是如何工作的?

if not ctx.invoked_subcommand:

允许仅在 "no command" 情况下调用组命令,并且

@click.group(cls=DefaultCommandGroup, invoke_without_command=True)

结合:

@main.command(default_command=True)

如果找不到其他命令,则允许命令为 运行。

测试代码:

import click

@click.group(cls=DefaultCommandGroup, invoke_without_command=True)
@click.pass_context
def main(ctx):
    """My Great CLI"""
    if not ctx.invoked_subcommand:
        click.echo("Does A")

@main.command(default_command=True)
@click.argument('args', nargs=-1)
def default_cmd_with_args(args):
    """Command run without a command"""
    click.echo("Does B: {}".format(args))


@main.command()
def cmd_c1():
    """A c1 command"""
    click.echo("Does C1")


@main.command()
def cmd_c2():
    """A c2 command"""
    click.echo("Does C2")


if __name__ == "__main__":
    commands = (
        '',
        'random args',
        'cmd_c1',
        'cmd_c2',
        '--help',
    )

    import sys, time

    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for command in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + command)
            time.sleep(0.1)
            main(command.split())

        except BaseException as exc:
            if str(exc) != '0' and \
                    not isinstance(exc, (click.ClickException, SystemExit)):
                raise

结果:

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)]
-----------
> 
Does A
-----------
> random args
Does B: ('random', 'args')
-----------
> cmd_c1
Does C1
-----------
> cmd_c2
Does C2
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...

  My Great CLI

Options:
  --help  Show this message and exit.

Commands:
  <>      Command run without a command
  cmd_c1  A c1 command
  cmd_c2  A c2 command