Creating Basic Commands
In this tutorial, you will learn how to build a command-line interface (CLI) with multiple subcommands using the Typer class and the @app.command() decorator. You will create a user management tool that can create and delete users, while exploring how to configure command metadata and help output.
Prerequisites
To follow this tutorial, you need the typer package installed. If you want to see the enhanced help formatting, ensure rich is also installed.
Step 1: Initialize the Typer Application
The main entry point for any Typer application is the typer.main.Typer class. This object acts as a registry for your commands.
import typer
app = typer.Typer()
By creating an instance of Typer, you gain access to the @app.command() decorator, which you will use to register functions as CLI commands.
Step 2: Define a Basic Command
To turn a Python function into a CLI command, decorate it with @app.command(). Typer automatically inspects the function signature to determine the command's arguments.
@app.command()
def create(username: str):
"""
Create a new user with the given USERNAME.
"""
print(f"Creating user: {username}")
When you define a command:
- Function Name: The function name
createbecomes the command name in the CLI. If the function name has underscores (e.g.,create_user), Typer converts them to hyphens (create-user) by default. - Docstrings: The docstring of the function is automatically used as the help text for the command.
- Arguments: The
username: strparameter tells Typer that this command requires a string argument.
Step 3: Add Multiple Commands and Metadata
You can add as many commands as you need to the same app instance. You can also pass configuration parameters to the @app.command() decorator to control how the command appears in the help output.
@app.command(deprecated=True, help="Remove a user from the system.")
def delete(username: str):
"""
This docstring is ignored because the 'help' parameter is provided.
"""
print(f"Deleting user: {username}")
In this example:
deprecated=True: This marks the command as deprecated in the help output, warning users that it may be removed in the future.help="...": This explicitly sets the help text, overriding the function's docstring.
Step 4: Organize Commands with Rich Help Panels
If you have many commands, you can group them into logical sections in the help output using the rich_help_panel parameter. This requires the rich library to be installed.
@app.command(rich_help_panel="Maintenance")
def sync():
"""
Synchronize user data with the remote server.
"""
print("Syncing...")
When a user runs --help, the sync command will be displayed under a specific "Maintenance" header rather than the default "Commands" list.
Step 5: Execute the Application
To make your script executable from the command line, call the app instance as a function. This triggers the Typer.__call__ method, which handles argument parsing and command execution.
if __name__ == "__main__":
app()
Complete Working Example
Combining all the steps, here is a complete script based on the docs_src/commands/help/tutorial003_py310.py and tutorial006_py310.py examples:
import typer
# Initialize the app with Rich markup enabled for help text
app = typer.Typer(rich_markup_mode="rich")
@app.command()
def create(username: str):
"""
[green]Create[/green] a new user. :sparkles:
"""
print(f"Creating user: {username}")
@app.command(deprecated=True)
def delete(username: str):
"""
[red]Delete[/red] a user. :x:
"""
print(f"Deleting user: {username}")
@app.command(rich_help_panel="Maintenance")
def sync():
"""
[blue]Synchronize[/blue] the system. :recycle:
"""
print("Syncing the system")
if __name__ == "__main__":
app()
Verifying the Result
You can now run your application from the terminal:
- View Help: Run
python main.py --help. You will see the commands listed, withdeletemarked as deprecated andsyncgrouped under "Maintenance". - Run a Command: Run
python main.py create hiro.- Output:
Creating user: hiro
- Output:
- Missing Arguments: Run
python main.py create. Typer will automatically show an error message indicating that theusernameargument is missing.
Next Steps
Now that you can create basic commands, you can explore Command Contexts to access the underlying click.Context or learn about Sub-Typer instances to nest groups of commands into a hierarchical structure.