python-3.xpython-click

How to create click subcommands in python?


Having looked at the documentation for commands and groups I did not find anything helpful for creating subcommands with click (version 7.1.2). Either I missed it or it is described in a very weird way.

What I want to do is to have a subcommand so I can do e.g.

python myscript.py sub1
python myscript.py sub2

which executes two different functions. Here is what I have tried:

import click

@click.group()
def sub1():
    print("sub1")

@click.group()
def sub2():
    print("sub2")

also I tried this:

import click

@click.command()
def sub1():
    print("sub1")

@click.command()
def sub2():
    print("sub2")

neither this works:

import click

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

@cli.command("sub1")
def sub1():
    print("sub1")

@cli.command("sub2")
def sub2():
    print("sub2")

But this does not seem to work (i.e. the print statements are never executed). How to do it right? And where exactly is this documented?

Also I get the same behavior when trying the exact given example from the documentation:

import click
@click.group()
@click.option('--debug/--no-debug', default=False)
def cli(debug):
    click.echo(f"Debug mode is {'on' if debug else 'off'}")

@cli.command()  # @cli, not @click!
def sync():
    click.echo('Syncing') 

no output at all!


Solution

  • To create subcommands with click, and to make it work when you call your code like

    python mycode.py 
    

    you need to define the __main__ thingy:

    import click
    
    @click.group()
    def cli():
        pass
    
    @cli.command("sub1")
    def sub1():
        print("sub1")
    
    @cli.command("sub2")
    def sub2():
        print("sub2")
    
    if __name__ == "__main__":
       cli() 
    

    They seem to have forgotten that to mention in their documentation, or it is hidden somewhere.