Search code examples
pythonclickpython-click

Click (Meta) Command to run a list of commands


I need to be able to trigger multiple click commands from one command on the CLI

Let's say I have a click group

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

@cli.command()
def a():
    print("A")

@cli.command()
def b():
    print ("B")

What functionality should I add to run an ordered list of the commands like the following?

$ python -m my_cli_module a,b
A
B

The goal is that there are shared variables which get initialized for each of my commands. The init is expensive and I'd like to run the init exactly once.


Solution

  • To chain your commands, you have to pass chain=True to your group. For more information see this part of the documentation.

    You could use the @click.pass_context decorator on the group to store the result of your initialisation:

    @click.group(chain=True)
    @click.pass_context
    def cli(ctx):
        # Your init here resulting in an object
        ctx.obj = the_result_of_your_init
    

    and then you need to use the @click.pass_obj decorator on the commands to use the result object:

    @cli.command()
    @click.pass_obj
    def a(my_obj): # The first param of the command is the passed object
        print("A")
    
    

    The pattern above is useful to share resources. I used it to share my sqlite db connection as an example.

    For more information see the following documents:

    pass_context documentation

    pass_obj documentation

    Another way to achieve this is to use multi command pipelines.