如何为多个命令定义通用的 python-click 选项?

Ale*_*lex 8 python python-3.x python-click

在 python 3.8 中,我想定义一些多个命令通用的单击选项。我尝试了以下代码:

import click


@click.group()
@click.option(
    "-v",
    "--verbose",
    count=True,
    default=0,
    help="-v for DEBUG",
)
@click.option(
    "--path",
    help="Main Path.",
)
def cli():
  pass


@click.command("list")
@click.option(
    "--list-option",
    help="Special option for list command.",
)
def my_list_command(verbose, path, list_option):
    print(verbose, path, list_option)

@click.command("find")
@click.option(
    "--find-option",
    help="Special option for find command.",
)
def my_find_command(verbose, path, find_option):
    print(verbose, path, find_option)

cli.add_command(my_list_command)
cli.add_command(my_find_command)

if __name__ == '__main__':
    cli()
Run Code Online (Sandbox Code Playgroud)

但是当我尝试运行命令时

python script.py list
Run Code Online (Sandbox Code Playgroud)

我收到一个错误

TypeError: cli() got an unexpected keyword argument 'verbose'
Run Code Online (Sandbox Code Playgroud)

我想要的是该命令list具有以下三个选项:verbosepathlist-option该命令find具有以下三个选项:verbosepathfind-option。我不想定义verbose和的选项path两次。

有没有办法做到这一点?

我也尝试过使用,@click.pass_context但这似乎并不能解决问题。

L3v*_*han 15

您当前定义它的方式将起作用,但该--verbose选项属于主命令组,因此您需要将其称为python script.py --verbose list(并且my_find_command不会my_list_command仅将其作为参数接收cli)。

要在多个命令中使用相同的选项而不需要太多重复,您可以将其分配给一个变量,然后使用它两次:

verbose_option = click.option(
    "-v",
    "--verbose",
    count=True,
    default=0,
    help="-v for DEBUG",
)

...

@click.command()
@verbose_option
def foo(verbose):
    ...

@click.command()
@verbose_option
def bar(verbose):
    ...
Run Code Online (Sandbox Code Playgroud)

不相关,但当我们这样做时:有一种更简单的命令分组方法,无需执行以下操作cli.add_command(my_find_command):只需使用@cli.command()而不是@click.command()

import click

option_verbose = click.option(
    "-v",
    "--verbose",
    count=True,
    default=0,
    help="-v for DEBUG",
)

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


@cli.command("list")
@option_verbose
@click.option(
    "--list-option",
    help="Special option for list command.",
)
def my_list_command(verbose, list_option):
    print(verbose, list_option)

@cli.command("find")
@option_verbose
@click.option(
    "--find-option",
    help="Special option for find command.",
)
def my_find_command(verbose, list_option):
    print(verbose, list_option)

if __name__ == '__main__':
    cli()
Run Code Online (Sandbox Code Playgroud)

如果您想要应用多个选项,您可以定义自己的装饰器来调用参数上的所有这些选项:

verbose_option = click.option(
    "-v",
    "--verbose",
    count=True,
    default=0,
    help="-v for DEBUG",
)

...

@click.command()
@verbose_option
def foo(verbose):
    ...

@click.command()
@verbose_option
def bar(verbose):
    ...
Run Code Online (Sandbox Code Playgroud)