You can normally just let the code of your CLI program finish its execution, but in some scenarios, you might want to terminate at some point in the middle of it. And prevent any subsequent code to run.
This doesn't have to mean that there's an error, just that nothing else needs to be executed.
In that case, you can raise a typer.Exit() exception:
importtyperexisting_usernames=["rick","morty"]defmaybe_create_user(username:str):ifusernameinexisting_usernames:print("The user already exists")raisetyper.Exit()else:print(f"User created: {username}")defsend_new_user_notification(username:str):# Somehow send a notification here for the new user, maybe an emailprint(f"Notification sent for new user: {username}")defmain(username:str):maybe_create_user(username=username)send_new_user_notification(username=username)if__name__=="__main__":typer.run(main)
There are several things to see in this example.
The CLI program is the function main(), not the others. This is the one that takes a CLI argument.
The function maybe_create_user() can terminate the program by raising typer.Exit().
If the program is terminated by maybe_create_user() then send_new_user_notification() will never execute inside of main().
Check it:
fast βpython main.py Camila User created: Camila Notification sent for new user: Camila
π¬ Try with an existing userpython main.py rick The user already exists
π¬ Notice that the notification code was never run, the second message is not printed restart β»
Tip
Even though you are raising an exception, it doesn't necessarily mean there's an error.
This is done with an exception because it works as an "error" and stops all execution.
But then Typer (actually Click) catches it and just terminates the program normally.
typer.Exit() takes an optional code parameter. By default, code is 0, meaning there was no error.
You can pass a code with a number other than 0 to tell the terminal that there was an error in the execution of the program:
importtyperdefmain(username:str):ifusername=="root":print("The root user is reserved")raisetyper.Exit(code=1)print(f"New user created: {username}")if__name__=="__main__":typer.run(main)
Check it:
fast βpython main.py Camila New user created: Camila
π¬ Print the result code of the last program executedecho $? 0
π¬ Now make it exit with an errorpython main.py root The root user is reserved
π¬ Print the result code of the last program executedecho $? 1
π¬ 1 means there was an error, 0 means no errors. restart β»
Tip
The error code might be used by other programs (for example a Bash script) that execute your CLI program.
There's a special exception that you can use to "abort" a program.
It works more or less the same as typer.Exit() but will print "Aborted!" to the screen and can be useful in certain cases later to make it explicit that the execution was aborted:
importtyperdefmain(username:str):ifusername=="root":print("The root user is reserved")raisetyper.Abort()print(f"New user created: {username}")if__name__=="__main__":typer.run(main)
Check it:
fast βpython main.py Camila New user created: Camila
π¬ Now make it exit with an errorpython main.py root The root user is reserved Aborted!