[Python] Python command line tool with subcommands in typer - How do I include a Typer...

Discussão em 'Python' iniciado por Stack, Março 5, 2025.

  1. Stack

    Stack Membro Participativo

    When writing a command line tool in Python using Typer one can create a CLI with commands and even subcommands. If you define a CLI with only one command the CLI will be optimized such that you do not have to provide the command - let's call this modul cli_a.py:

    #!env python

    import typer

    app = typer.Typer()

    @app.command()
    def main():
    print('This is the output of main')

    if __name__ == '__main__':
    app()



    Now, you can call this CLI like so

    $ ./cli_a.py --help

    Usage: cli_a.py [OPTIONS]

    ╭─ Options ───────────────────────────────────────────────────────────────────╮
    │ --install-completion Install completion for the current shell. │
    │ --show-completion Show completion for the current shell, to │
    │ copy it or customize the installation. │
    │ --help Show this message and exit. │
    ╰─────────────────────────────────────────────────────────────────────────────╯


    and

    $ ./cli_a.py
    This is the output of main


    Notice, that there has to be no command called main!

    On the other hand you can have a CLI with multiple commands - let's call this cli_b.py:

    #!env python
    import typer

    app = typer.Typer()

    @app.command()
    def cmd1():
    print('This is the output of cmd1')

    @app.command()
    def cmd2():
    print('This is the output of cmd2')

    if __name__ == '__main__':
    app()


    With the following output:

    $ ./cli_b.py --help

    Usage: cli_b.py [OPTIONS] COMMAND [ARGS]...

    ╭─ Options ───────────────────────────────────────────────────────────────────╮
    │ --install-completion Install completion for the current shell. │
    │ --show-completion Show completion for the current shell, to │
    │ copy it or customize the installation. │
    │ --help Show this message and exit. │
    ╰─────────────────────────────────────────────────────────────────────────────╯
    ╭─ Commands ──────────────────────────────────────────────────────────────────╮
    │ cmd1 │
    │ cmd2 │
    ╰─────────────────────────────────────────────────────────────────────────────╯


    In this case you have to provide the command to be called:

    $ ./cli_b.py cmd1
    This is the output of cmd1


    I want to combine these two CLI into one - let's call this super_cli.py:

    #!env python
    import typer
    import cli_a
    import cli_b

    app = typer.Typer()
    app.add_typer(cli_a.app, name='cli_a')
    app.add_typer(cli_b.app, name='cli_b')

    if __name__ == '__main__':
    app()


    This behaves as expected for cli_b:

    $ ./super_cli.py cli_b cmd1
    This is the output of cmd1


    But requires an unwanted additional command main on cli_a:

    $ ./super_cli.py cli_a main
    This is the output of main


    How can it be achieved that cli_a is callable without specifying the additional command main?

    I was expecting to get

    $ ./super_cli.py cli_a
    This is the output of main


    but I do get

    $ ./super_cli.py cli_a
    Usage: super_cli.py cli_a [OPTIONS] COMMAND [ARGS]...
    Try 'super_cli.py cli_a --help' for help.
    ╭─ Error ─────────────────────────────────────────────────────────────────────╮
    │ Missing command. │
    ╰─────────────────────────────────────────────────────────────────────────────╯


    instead.

    Continue reading...

Compartilhe esta Página