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

时间:2019-02-26 23:56:47

标签: python python-3.x command-line-interface python-click

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

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

myapp "some argument"-会做B事。B事受论点“某些论点”的影响。

myapp command-将启动具有功能C的“命令”(由装饰器@cli.command表示)。这将受到单击所提供的所有事物(例如@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命令。 我不喜欢这种解决方案。这似乎不是干净的解决方案。为了正常运行,需要使用全局变量和一些讨厌的技巧。

你们中有人知道更好的方法,如何实现吗?

1 个答案:

答案 0 :(得分:1)

一种方法是将here给出的两个答案结合起来:

关键要素:

@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:

仅在“无命令”情况下允许组命令被调用,并且

@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