使用python click,如何避免重复多个子命令使用的参数代码

使用python click,如何避免重复多个子命令使用的参数代码,python,command-line-interface,python-click,Python,Command Line Interface,Python Click,我有一组子命令,所有子命令都对URL列表进行操作,这些URL可以选择作为参数传递。如何将此参数指定给组,以避免在每个子命令上重复参数定义 当前代码: from config import site_list @click.group() def cli(): pass @cli.command() @cli.argument('sites', nargs=-1) def subcommand_one(): if sites: site_list = sites

我有一组子命令,所有子命令都对URL列表进行操作,这些URL可以选择作为参数传递。如何将此参数指定给组,以避免在每个子命令上重复参数定义

当前代码:

from config import site_list

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

@cli.command()
@cli.argument('sites', nargs=-1)
def subcommand_one():
    if sites:
        site_list = sites
    etc...

@cli.command()
@cli.argument('sites', nargs=-1)
def subcommand_two():
    if sites:
        site_list = sites
    etc...
调用示例:

$ python sites.py subcommand_one www.example.com www.example2.com
我尝试将参数装饰器移动到组中,如下所示:

@click.group()
@click.argument('sites', nargs=-1)
def cli(sites):
    if sites:
        site_list = sites
但是我会得到这个错误:

$ python sites.py subcommand_one
Usage: sites.py [OPTIONS] [SITES] COMMAND [ARGS]...
Try "sites.py --help" for help.

Error: Missing command.

click.argument
与其他任何变量一样只返回一个decorator,因此您可以将其分配给某个变量:

import click

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

sites_argument = click.argument('sites', nargs=-1)

@cli.command()
@sites_argument
def subcommand_one(sites):
    ...

@cli.command()
@sites_argument
def subcommand_two(sites):
    ...

如果有一个特定的
nargs=-1
参数,您只想修饰到组中,但适用于 根据需要执行所有命令,您可以使用一些额外的管道来执行这些操作,如:

这个答案的灵感来源于答案

自定义类 使用自定义类: 要使用自定义类,请将
cls
参数传递给
click.group()
decorator,使用
@GroupNArgsForCommands.command_参数
特殊参数的装饰器,然后添加 与任何命令的特殊参数同名的参数

@click.group(cls=GroupNArgsForCommands)
@GroupNArgsForCommands.command_argument('special', nargs=-1)
def a_group():
    """My project description"""

@a_group.command()
def a_command(special):
    """a command under the group"""
这是怎么回事? 这是因为
click
是一个设计良好的OO框架。
@click.group()
装饰程序通常 实例化一个
click.Group
对象,但允许使用
cls
参数过度执行此行为。
因此,在我们自己的类中继承
click.Group
并超越所需的方法是一件相对容易的事情

在本例中,我们将跳过
单击.Group.add_command()
,以便在添加命令时可以进行检查 命令回调参数,查看它们是否与任何特殊参数同名。 如果它们匹配,参数将被添加到命令的参数中,就像它被直接修饰一样

此外,
GroupNArgsForCommands
实现了一个
command\u参数()
方法。此方法用作 添加特殊参数而不是使用
click.argument()

测试班 结果:
我认为通过使用
@Click.pass\u上下文
,Click支持一个实际的解决方案

如果要定义一组命令,这些命令共享一个公共参数和一个公共选项,则可以在组级别上定义这些命令,并将它们添加到上下文对象中,如

@click.group(chain=True)
@click.argument(“数据集目录”,type=click.Path(exists=True))
@单击.option(“-s”,”--split name),help=“要预处理的拆分”,required=True,
默认值=[“列车集”、“devset”、“测试集”],显示(默认值=真)
@单击。传递上下文
def cli(ctx、数据集目录、拆分名称):
"""
为培训准备数据集
DATASET\u目录数据目录的绝对路径。
"""
ctx.确保对象(dict)
ctx.obj[“目录”]=数据集目录
ctx.obj[“拆分”]=拆分名称
然后,该组的各个命令可以通过上下文传递,并使用上下文对象中的值,而不是定义它们自己的参数和选项


@cli.命令(“创建”)
@单击。传递上下文
def创建(ctx):
从csv(ctx.obj[“DIRECTORY”]、ctx.obj[“SPLITS”])创建\u语义\u json\u
@cli.命令(“标记化”)
@单击。传递上下文
def标记化(ctx):
预处理\u标记化\u语义\u json(ctx.obj[“目录”]、ctx.obj[“拆分”])
然后可以调用以下命令:


my cli app/path/to/data create tokenize

我想使该参数成为可选参数并提供默认值,但当我尝试
sites\u参数=click.argument('sites',nargs=-1,default=site\u list)时
我得到了这个错误
TypeError:nargs=-1与默认值结合使用是不受支持的。
在这里分配默认值的最佳方法是什么?您可以没有默认值,在函数测试中使用空列表,也可以使用回调。这是我所问问题的最佳答案。然而,维亚坦的答案对我来说可能是一个更好的解决方案。我试图理解如何在他的解决方案中为参数提供默认值。
@click.group(cls=GroupNArgsForCommands)
@GroupNArgsForCommands.command_argument('special', nargs=-1)
def a_group():
    """My project description"""

@a_group.command()
def a_command(special):
    """a command under the group"""
import click

@click.group(cls=GroupNArgsForCommands)
@GroupNArgsForCommands.command_argument('sites', nargs=-1)
def cli():
    click.echo("cli group")

@cli.command()
def command_one(sites):
    click.echo("command_one: {}".format(sites))

@cli.group()
def subcommand():
    click.echo("subcommand group")

@subcommand.command()
def one():
    click.echo("subcommand_one")

@subcommand.command()
def two(sites):
    click.echo("subcommand_two: {}".format(sites))

if __name__ == "__main__":
    commands = (
        'command_one site1 site2',
        'command_one site1',
        'command_one',
        'subcommand',
        'subcommand one site1 site2',
        'subcommand one site1',
        'subcommand one',
        'subcommand two site1 site2',
        'subcommand two site1',
        'subcommand two',
        '--help',
        'command_one --help',
        'subcommand --help',
        'subcommand one --help',
        'subcommand two --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)
            cli(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)]
-----------
> command_one site1 site2
cli group
command_one: ('site1', 'site2')
-----------
> command_one site1
cli group
command_one: ('site1',)
-----------
> command_one
cli group
command_one: ()
-----------
> subcommand
cli group
Usage: test.py subcommand [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  one
  two
-----------
> subcommand one site1 site2
Usage: test.py subcommand one [OPTIONS]

Error: Got unexpected extra arguments (site1 site2)
cli group
subcommand group
-----------
> subcommand one site1
cli group
subcommand group
Usage: test.py subcommand one [OPTIONS]

Error: Got unexpected extra argument (site1)
-----------
> subcommand one
cli group
subcommand group
subcommand_one
-----------
> subcommand two site1 site2
cli group
subcommand group
subcommand_two: ('site1', 'site2')
-----------
> subcommand two site1
cli group
subcommand group
subcommand_two: ('site1',)
-----------
> subcommand two
cli group
subcommand group
subcommand_two: ()
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  command_one
  subcommand
-----------
> command_one --help
cli group
Usage: test.py command_one [OPTIONS] [SITES]...

Options:
  --help  Show this message and exit.
-----------
> subcommand --help
cli group
Usage: test.py subcommand [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  one
  two
-----------
> subcommand one --help
cli group
subcommand group
Usage: test.py subcommand one [OPTIONS]

Options:
  --help  Show this message and exit.
-----------
> subcommand two --help
cli group
subcommand group
Usage: test.py subcommand two [OPTIONS] [SITES]...

Options:
  --help  Show this message and exit.
-----------
> 
Usage: test.py [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  command_one
  subcommand