Exceptions and Errors¶
When your code has errors and you run it, it will show the error and an exception.
Typer does some tricks to help you detect those errors quickly.
Example Broken App¶
Let's take this example broken app:
import typer
def main(name: str = "morty"):
print(name + 3)
if __name__ == "__main__":
typer.run(main)
This code is broken because you can't sum a string and a number (name + 3
).
Exceptions with Rich¶
If you have Rich installed (for example if you installed "typer[all]"
), Typer will use it to automatically show you nicely printed errors.
It will omit all the parts of the traceback (the chain of things that called your function) that come from the internal parts in Typer and Click.
So, the error you see will be much clearer and simpler, to help you detect the problem in your code quickly:
Exceptions without Rich¶
If you don't have Rich installed, Typer will still do some tricks to show you the information as clearly as possible:
Disable Local Variables for Security¶
If your Typer application handles delicate information, for example a password, a key, a token, then it could be problematic if the automatic errors show the value in those local variables.
This would be relevant in particular if your CLI application is being run on some CI (continuous integration) system that is recording the logs.
The default errors above, when using Rich, show a section with:
name = 'morty'
In this case, name
is a local variable, it comes from a parameter passed to the function.
But if it was something like a password, you would have liked to hide it.
In that case, you can create the typer.Typer()
application explicitly and set the parameter pretty_exceptions_show_locals=False
:
import typer
app = typer.Typer(pretty_exceptions_show_locals=False)
@app.command()
def main(password: str):
print(password + 3)
if __name__ == "__main__":
app()
And now when you run it, you will see the error without the local variables:
Note that you passed the password supersecret
, but it's not shown anywhere in the error message.
Being able to see the values of local variables is normally very helpful to diagnose, debug, and fix problems, but if you are dealing with delicate information, now you know how to secure it. 🔒
Disable Short Output¶
If you want to show the full exception, including the parts in Typer and Click, you can use the parameter pretty_exceptions_short=False
:
import typer
app = typer.Typer(pretty_exceptions_short=False)
@app.command()
def main(name: str = "morty"):
print(name + 3)
if __name__ == "__main__":
app()
Now when you run it, you will see the whole output:
Set Output Width¶
If you want to control the width of the yellow and red Rich exception borders, you can set the parameter pretty_exceptions_width
to a specific integer (it's 100 by default):
import typer
app = typer.Typer(pretty_exceptions_width=120)
@app.command()
def main(name: str = "morty"):
deep_dict_or_json = {
"this_is_a_long_key": {
"this_is_the_next_long_key": {
"this_is_the_next_long_key": {
"this_is_the_next_long_key": {
"this_is_the_next_long_key": {
"this_is_the_next_long_key": {
"this_is_the_next_long_key": {
"this_is_the_next_long_key": {
"this_is_the_next_long_key": {
"this_is_the_next_long_key": {
"and_once_again_a_very_long_key": {
"but_this_is_not_the_end": {
"end": True
}
}
}
}
}
}
}
}
}
}
}
}
}
print(name + 3)
print(deep_dict_or_json)
if __name__ == "__main__":
app()
This prevents artificial line breaks in cases where there is sufficient horizontal space on the console.
Disable Pretty Exceptions¶
You can also entirely disable pretty exceptions with the parameter pretty_exceptions_enable=False
:
import typer
app = typer.Typer(pretty_exceptions_enable=False)
@app.command()
def main(name: str = "morty"):
print(name + 3)
if __name__ == "__main__":
app()
And now you will see the full standard exception as with any other Python program:
You could also achieve the same with the environment variable _TYPER_STANDARD_TRACEBACK=1
.
This will work for any other Typer program too, in case you need to debug a problem in a Typer program made by someone else: