Initializing the Application
In this tutorial, you will learn how to initialize a CLI application using the Typer class. You will build a configured entry point that includes custom help text, improved user experience for new users, and enhanced debugging features.
Prerequisites
To follow this tutorial, you need to have the typer package installed. If you want to use the advanced formatting and exception features, you should also have rich installed.
pip install "typer[all]"
Step 1: Create the Application Instance
The foundation of any Typer project is an instance of the typer.Typer class. This object acts as the main container where you will register your commands.
Create a file named main.py and add the following code:
import typer
app = typer.Typer()
@app.command()
def hello():
print("Hello World")
if __name__ == "__main__":
app()
By instantiating typer.Typer(), you create a top-level CLI object. The @app.command() decorator is then used to add functionality to this instance. The final if __name__ == "__main__": app() block ensures that the application executes when the script is run directly.
Step 2: Add Help Documentation and Metadata
You can provide context to your users by adding a help description and an epilog (text that appears at the end of the help output).
Update your app initialization:
app = typer.Typer(
help="Awesome CLI Tool to manage your tasks.",
epilog="Made with :heart: by the Typer team"
)
The help parameter provides the main description for your CLI when a user runs --help. The epilog is useful for adding version info, credits, or additional links at the very bottom of the help screen.
Step 3: Improve User Experience with no_args_is_help
By default, if a user runs your CLI without any arguments, Typer might do nothing or show an error if a command is required. You can change this so it automatically displays the help page.
Modify your initialization:
app = typer.Typer(
help="Awesome CLI Tool",
no_args_is_help=True
)
Setting no_args_is_help=True is a common pattern for complex CLIs. It ensures that users who are unsure how to use the tool are immediately presented with the available commands and options.
Step 4: Enable Rich Formatting for Help Text
If you have rich installed, you can use Markdown or Rich markup in your help strings to make them more readable and visually appealing.
Update your initialization to enable Markdown:
app = typer.Typer(rich_markup_mode="markdown")
@app.command()
def create(username: str):
"""
**Create** a new user.
This command supports *Markdown* formatting in the docstring!
"""
print(f"Creating user: {username}")
By setting rich_markup_mode="markdown", Typer will parse the docstrings of your commands as Markdown. This allows you to use bold text, italics, and even code blocks in your CLI help output.
Step 5: Configure Debugging and Exceptions
Typer can provide "pretty" exceptions that are easier to read than standard Python tracebacks. For development, you can even configure it to show the values of local variables when an error occurs.
Update your initialization:
app = typer.Typer(
pretty_exceptions_show_locals=True,
pretty_exceptions_short=False
)
pretty_exceptions_show_locals=True: When an exception occurs, Typer will print the values of variables in the local scope, which is invaluable for debugging.pretty_exceptions_short=False: This ensures the full stack trace is shown rather than a truncated version.
Complete Working Result
Combining all these steps, your main.py should look like this:
import typer
app = typer.Typer(
name="my-app",
help="""
# My Awesome CLI
This is a **fully configured** Typer application.
""",
epilog="Visit https://typer.tiangolo.com for more info.",
no_args_is_help=True,
rich_markup_mode="markdown",
pretty_exceptions_show_locals=True
)
@app.command()
def create(username: str):
"""
Create a user with a **username**.
"""
print(f"Creating user: {username}")
@app.command()
def delete(username: str):
"""
Delete a user.
"""
print(f"Deleting user: {username}")
if __name__ == "__main__":
app()
Next Steps
Now that you have initialized your application, you can:
- Learn how to define complex inputs using Arguments and Options.
- Organize your code by nesting multiple Typer apps using
app.add_typer(). - Customize global behavior using the
@app.callback()decorator.