【问题标题】:Share a sub-command among multiple top level commands在多个顶级命令之间共享一个子命令
【发布时间】:2019-06-10 22:02:38
【问题描述】:

我有一个包含多个顶级入口点的 Python 项目,我们称它们为 foobar。两个入口点使用相同的代码库,我希望使用实现version() 命令的完全相同的代码来实现foo versionbar version 命令。

所以,在 foo.py 中,我会说

import click

@click.group()
def foo():

@foo.command
@option('--long', ...)
@option('--check', ...)
def version(long, check):
    ...

bar 中相同。如何避免在两个文件中重复命令定义?

【问题讨论】:

    标签: python command-line-interface python-click


    【解决方案1】:

    参考this answer,您可以构建一个单击命令并将其作为两个单独的操作添加到多个组或命令中。

    构建点击命令:

    首先我们需要构建一个点击命令。我们将使用辅助函数来装饰可导入命令,例如:

    import click
    
    def importable_command(*args, **kwargs):
        def decorator(f):
            return click.decorators.command(*args, **kwargs)(f)
        return decorator
    
    
    @importable_command('version')
    @click.option('--long')
    @click.option('--check')
    def version_cmd(long, check):
        click.echo('version long: {}'.format(long))
        click.echo('version check: {}'.format(check))
    

    将命令添加到组:

    然后我们可以导入命令并将其添加到一个组中:

    from where-ever-we-defined-it import version_cmd
    
    # Add our version command to this group
    a_group.add_command(version_cmd)
    

    测试代码:

    import click
    
    def importable_command(*args, **kwargs):
        def decorator(f):
            return click.decorators.command(*args, **kwargs)(f)
        return decorator
    
    
    @importable_command('version')
    @click.option('--long')
    @click.option('--check')
    def version_cmd(long, check):
        click.echo('version long: {}'.format(long))
        click.echo('version check: {}'.format(check))
    
    
    @click.group()
    def cli():
        """An Awesome CLI"""
    
    
    # Add our version command to this group
    cli.add_command(version_cmd)
    
    if __name__ == "__main__":
        commands = (
            'version --long a_long',
            'version --help',
            '--help',
        )
    
        import sys, time
    
        time.sleep(1)
        print('Click Version: {}'.format(click.__version__))
        print('Python Version: {}'.format(sys.version))
        for cmd in commands:
            try:
                time.sleep(0.1)
                print('-----------')
                print('> ' + cmd)
                time.sleep(0.1)
                cli(cmd.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)]
    -----------
    > version --long a_long
    version long: a_long
    version check: None
    -----------
    > version --help
    Usage: test.py version [OPTIONS]
    
    Options:
      --long TEXT
      --check TEXT
      --help        Show this message and exit.
    -----------
    > --help
    Usage: test.py [OPTIONS] COMMAND [ARGS]...
    
      An Awesome CLI
    
    Options:
      --help  Show this message and exit.
    
    Commands:
      version
    

    【讨论】:

    • 非常酷。谢谢你。不知何故,我的思想总是被装饰魔法所扭曲。
    • 我在使它工作时遇到了一些麻烦。我不断得到:文件“/build/snaprr_infra/common_cli.py”,第 40 行,在 common.add_command(autoupgrade_cmd) 文件“/usr/local/lib/python3.6/dist-packages/click/core. py",第 1221 行,在 add_command name = name 或 cmd.name AttributeError: 'NoneType' object has no attribute 'name'
    • 您的样本工作正常,即使我拆分它...一定是其他问题。
    • 我发现了不相关的问题...再次感谢。
    猜你喜欢
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    • 2017-05-27
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    相关资源
    最近更新 更多