🛡️ Flask Error Handling & Debugging: Your Safety Net
Imagine you’re a circus performer walking on a tightrope. Below you, there’s a big, bouncy safety net. If you slip, you don’t crash to the ground—you land safely and can try again! In Flask, error handling is your safety net. When something goes wrong in your app, instead of crashing, Flask catches the problem and shows users a friendly message.
🎯 What You’ll Learn
| Topic | What It Does |
|---|---|
abort() function |
Stop everything and show an error |
| Custom error pages | Make errors look pretty |
| HTTP error handlers | Catch specific error types |
| Debugging | Find and fix bugs |
| Logging | Keep a diary of what happens |
| Error logging | Record problems for later |
🚨 The abort() Function: The Emergency Stop Button
Think of abort() like a big red STOP button on a machine. When you press it, everything stops immediately!
When Do You Use It?
- User tries to see a page they’re not allowed to see
- Something important is missing
- A request doesn’t make sense
Simple Example
from flask import Flask, abort
app = Flask(__name__)
@app.route('/secret')
def secret_page():
user_logged_in = False
if not user_logged_in:
abort(403) # STOP! Not allowed!
return "Welcome to the secret!"
Common abort() Codes
graph TD A[abort Codes] --> B[404] A --> C[403] A --> D[400] A --> E[500] B --> B1[Page Not Found] C --> C1[Forbidden/Not Allowed] D --> D1[Bad Request] E --> E1[Server Error]
| Code | Meaning | Real-Life Example |
|---|---|---|
| 404 | Not Found | Looking for a toy that doesn’t exist |
| 403 | Forbidden | Trying to enter without permission |
| 400 | Bad Request | Asking for something silly |
| 500 | Server Error | The machine broke inside |
🎨 Custom Error Pages: Making Errors Pretty
When your friend trips, you don’t just say “ERROR!” You say “Oops! Are you okay?” Custom error pages do the same thing for your website users.
Creating a Custom 404 Page
from flask import Flask, render_template
app = Flask(__name__)
@app.errorhandler(404)
def page_not_found(error):
return render_template('404.html'), 404
The Template (404.html)
<!DOCTYPE html>
<html>
<head>
<title>Oops!</title>
</head>
<body>
<h1>😢 Page Not Found</h1>
<p>We looked everywhere but
couldn't find that page!</p>
<a href="/">Go Home</a>
</body>
</html>
Why Custom Pages Matter
graph TD A[User Hits Error] --> B{Default Page?} B -->|Yes| C[Ugly Technical Message] B -->|No Custom| D[Friendly Helpful Message] C --> E[😕 User Confused] D --> F[😊 User Stays Happy]
🎣 HTTP Error Handlers: Catching Different Problems
Think of error handlers like fishing nets. Each net catches a different type of fish. Each handler catches a different type of error!
Handling Multiple Errors
from flask import Flask, render_template
app = Flask(__name__)
@app.errorhandler(404)
def not_found(error):
return "Page not found! 🔍", 404
@app.errorhandler(403)
def forbidden(error):
return "You can't go there! 🚫", 403
@app.errorhandler(500)
def server_error(error):
return "Oops, we broke! 💥", 500
Catching All Errors at Once
from werkzeug.exceptions import HTTPException
@app.errorhandler(HTTPException)
def handle_exception(e):
return f"Error {e.code}: {e.name}", e.code
🔍 Debugging Flask Applications: Finding the Bugs
Debugging is like being a detective! 🕵️ When something isn’t working, you look for clues to find out what went wrong.
Turning On Debug Mode
from flask import Flask
app = Flask(__name__)
if __name__ == '__main__':
app.run(debug=True) # Magic!
What Debug Mode Gives You
| Feature | What It Does |
|---|---|
| Auto-reload | App restarts when you change code |
| Error details | Shows exactly what went wrong |
| Interactive debugger | Click to explore the problem |
⚠️ WARNING: Never Use Debug in Production!
graph TD A[Debug Mode] --> B{Where?} B -->|Development| C[✅ Safe to Use] B -->|Production| D[❌ DANGEROUS!] C --> E[Find bugs easily] D --> F[Hackers can see secrets!]
Using Environment Variables (The Safe Way)
import os
from flask import Flask
app = Flask(__name__)
# Only enable debug if env says so
if os.environ.get('FLASK_DEBUG') == '1':
app.debug = True
📝 Logging Configuration: Your App’s Diary
Logs are like a diary for your app. They write down everything important that happens, so you can read it later!
Setting Up Basic Logging
import logging
from flask import Flask
app = Flask(__name__)
# Tell Python how to write the diary
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s %(levelname)s: %(message)s'
)
Log Levels (From Chatty to Serious)
graph TD A[Log Levels] --> B[DEBUG 🔬] A --> C[INFO ℹ️] A --> D[WARNING ⚠️] A --> E[ERROR ❌] A --> F[CRITICAL 💀] B --> B1[Super detailed] C --> C1[General updates] D --> D1[Something weird] E --> E1[Something broke] F --> F1[Everything broke!]
| Level | When to Use | Example |
|---|---|---|
| DEBUG | Testing details | “User clicked button” |
| INFO | Normal events | “User logged in” |
| WARNING | Small problems | “Disk getting full” |
| ERROR | Something failed | “Payment failed” |
| CRITICAL | App might crash | “Database gone!” |
Logging to a File
import logging
from flask import Flask
app = Flask(__name__)
# Create a file handler
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.WARNING)
# Set the format
formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s'
)
file_handler.setFormatter(formatter)
# Add to app's logger
app.logger.addHandler(file_handler)
🚨 Error Logging: Recording Problems
Error logging is like a security camera for your app. When something bad happens, you have a recording to review!
Automatic Error Logging
from flask import Flask
import logging
app = Flask(__name__)
@app.route('/divide')
def divide():
try:
result = 10 / 0 # Uh oh!
except Exception as e:
app.logger.error(f'Division failed: {e}')
return "Math is hard! 🤯", 500
return str(result)
Full Error Logging Setup
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask
app = Flask(__name__)
# Create rotating file handler
# (starts new file when old one gets big)
handler = RotatingFileHandler(
'errors.log',
maxBytes=10000,
backupCount=3
)
handler.setLevel(logging.ERROR)
# Nice format for errors
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s\n'
'%(message)s\n'
'---'
)
handler.setFormatter(formatter)
# Add to app
app.logger.addHandler(handler)
What Gets Logged
graph TD A[Something Breaks] --> B[Error Handler Catches It] B --> C[Log the Details] C --> D[Error Type] C --> E[When It Happened] C --> F[Where in Code] C --> G[What User Did]
🎯 Putting It All Together
Here’s a complete example using everything you learned:
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask, render_template, abort
app = Flask(__name__)
# === Logging Setup ===
logging.basicConfig(level=logging.DEBUG)
file_handler = RotatingFileHandler(
'app.log', maxBytes=10000, backupCount=3
)
file_handler.setLevel(logging.WARNING)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s'
))
app.logger.addHandler(file_handler)
# === Error Handlers ===
@app.errorhandler(404)
def not_found(error):
app.logger.warning(f'Page not found')
return "🔍 Page not found!", 404
@app.errorhandler(500)
def server_error(error):
app.logger.error(f'Server error: {error}')
return "💥 Something broke!", 500
# === Routes ===
@app.route('/user/<int:user_id>')
def get_user(user_id):
app.logger.info(f'Looking for user {user_id}')
if user_id > 100:
app.logger.warning(f'User {user_id} not found')
abort(404)
return f"Hello, User {user_id}!"
if __name__ == '__main__':
app.run(debug=True)
🌟 Quick Summary
| Concept | One-Liner |
|---|---|
abort() |
Emergency stop button |
| Custom error pages | Friendly error messages |
| Error handlers | Catch different error types |
| Debug mode | Detective mode (dev only!) |
| Logging | Your app’s diary |
| Error logging | Recording problems |
💪 You’ve Got This!
Remember: Errors aren’t failures—they’re opportunities to make your app better!
Every error you handle is like adding another pillow to your safety net. The more pillows, the softer the landing when something goes wrong.
Now go forth and handle those errors like a pro! 🚀