No matter how much your test your code, there might be an occassional exception raised during the execution of
one of the routes in your code. You cannot wrap all the code in a huge
try
-
except
block, but you
can use the built-in error-handling of Flask using the
errrohandler
hook that we have already
seen when we wanted to have a unified look for
404 page not found
.
Oputput of the crash
Visiting the http://localhost:5000/crash URL shows a stack trace like this on the command line:
[2020-06-26 10:33:29,633] INFO in app: crash route
[2020-06-26 10:33:29,633] ERROR in app: division by zero
Traceback (most recent call last):
File ".../flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File ".../flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File ".../flask/catch_exception/app.py", line 20, in crash
b = 3 / a
ZeroDivisionError: division by zero
127.0.0.1 - - [26/Jun/2020 10:33:29] "GET /crash HTTP/1.1" 200 -
The user only sees the word "exception".
Of course insted of returning that word, we could have used
render_template
to
render any page. The status code returned by the page will be 500 as indicated by the
second value returned.
Catching specific exceptions
In the above examples we use the catch-all
Exception
class, but you can be more specific
about the exceptions and you can return different pages based on the error type.
You could do this by checking the
type
of the
err
variable, but a probably cleaner way
is to set up separate exception handler hooks for each exception type you'd like to deal with:
examples/flask/catch_specific_exception/app.py
from flask import Flask
import datetime
app = Flask(__name__)
@app.errorhandler(Exception)
def server_error(err):
app.logger.exception(err)
return "Some general exception", 500
@app.errorhandler(ZeroDivisionError)
def server_error(err):
app.logger.exception(err)
return "Cannot divide by 0", 500
@app.route("/")
def main():
app.logger.info("main route")
return "Hello " + str(datetime.datetime.now())
@app.route("/crash")
def crash():
app.logger.info("crash route")
raise Exception("just crash")
@app.route("/calc")
def calc():
app.logger.info("calc route")
a = 0
b = 3 / a
Logging the Exception
In the above examples we keept using the app.logger.exception(err) expression to log
the exception and the stack trace. If you are not interested in the stack-trace you can use
the error logging method: app.logger.error(err).
If you have any comments or questions, feel free to post them on the source of this page in GitHub. Source on GitHub.
Comment on this post
Author: Gabor Szabo
Gábor who writes the articles of the Code Maven site offers courses in in the subjects
that are discussed on this web site.
Gábor helps companies set up test automation, CI/CD
Continuous Integration and Continuous Delivery and other DevOps related
systems. Gabor can help your team improve the development speed and reduce the risk of bugs.
He is also the author of a number of eBooks.
Contact Gabor if you'd like to hire his services.
If you would like to support his freely available work, you can do it via
Patreon, GitHub,
or PayPal.