如何为多个命令定义常用的Python单击选项?

hc2pp10m  于 2023-01-29  发布在  Python
关注(0)|答案(1)|浏览(112)

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

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()

但当我尝试运行命令时

python script.py list

我收到错误

TypeError: cli() got an unexpected keyword argument 'verbose'

我想要的是命令list有以下三个选项:verbosepathlist-option,并且命令find具有以下三个选项:verbosepathfind-option。我不想为verbosepath定义两次选项。
有什么办法吗?
我也试着使用@click.pass_context,但这似乎并不能解决这个问题。

ijnw1ujt

ijnw1ujt1#

您当前定义的方式可以正常工作,但是--verbose选项属于主命令组,因此您需要将其称为python script.py --verbose listmy_find_commandmy_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):
    ...

无关,但既然说到这里:有一种更简单的方法可以对命令进行分组,而不必执行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()

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

def common_options(fn):
    return click.option(
        "-v",
        "--verbose",
    )(
        click.option(
            "-n",
            "--dry-run",
        )(fn)
    )

相关问题