Flask入门教程(十五):错误处理与日志——打造健壮的Web应用

1. 自定义错误页面

默认情况下,Flask对404等错误会显示简单的黑底白字页面。使用@app.errorhandler装饰器可以为特定HTTP状态码定制错误页面:

复制代码
from flask import Flask, render_template

app = Flask(__name__)

# 处理404错误——页面未找到
@app.errorhandler(404)
def page_not_found(error):
    return render_template("404.html"), 404

# 处理500错误——服务器内部错误
@app.errorhandler(500)
def internal_error(error):
    return render_template("500.html"), 500

# 处理403错误——禁止访问
@app.errorhandler(403)
def forbidden(error):
    return render_template("403.html"), 403

templates/404.html:

复制代码
<!DOCTYPE html>
<html>
<head>
    <title>404 - 页面不存在</title>
    <style>
        body { text-align: center; padding-top: 60px; font-family: Arial; }
        h1 { font-size: 72px; color: #e74c3c; margin: 0; }
        p { color: #666; font-size: 18px; }
        a { color: #3498db; }
    </style>
</head>
<body>
    <h1>404</h1>
    <p>抱歉,你访问的页面不存在。</p>
    <p><a href="/">返回首页</a></p>
</body>
</html>

⚠️ 重要 :在errorhandler装饰的函数中,return必须显式带上状态码 。如果不写, 404,Flask会默认返回200状态码,浏览器和搜索引擎不会认为这是一个错误页面。

2. 异常类注册

除了状态码,@app.errorhandler还可以直接注册异常类:

复制代码
from werkzeug.exceptions import HTTPException

@app.errorhandler(HTTPException)
def handle_http_exception(error):
    """统一处理所有HTTP异常(如400, 401, 403, 404等)"""
    return f"""
    <h1>HTTP 错误 {error.code}</h1>
    <p>{error.description}</p>
    <p><a href="/">返回 RUNOOB 首页</a></p>
    """, error.code

# 也可以注册自定义异常类
class CustomError(Exception):
    pass

@app.errorhandler(CustomError)
def handle_custom_error(error):
    return "自定义错误发生了", 400

3. 使用abort触发错误

在视图函数中,使用abort()主动触发HTTP错误:

复制代码
from flask import abort

# 模拟文章数据库
articles = {
    1: {"title": "Flask 入门教程"},
    2: {"title": "Python 基础"},
}

@app.get("/article/<int:article_id>")
def view_article(article_id):
    article = articles.get(article_id)
    
    if article is None:
        # 文章不存在,返回404
        abort(404, description=f"文章 ID {article_id} 不存在")
    
    return f"<h1>{article['title']}</h1>"

@app.get("/admin")
def admin_panel():
    # 没有权限访问管理后台
    abort(403, description="你没有管理员权限")

abort()description参数会被传递给errorhandler,可以在自定义错误页面中显示详细信息。

4. 日志记录

Flask使用Python标准库的logging模块,通过app.logger即可记录日志。日志对于排查问题至关重要------不要只用print(),日志提供了更丰富的上下文和更好的控制力。

复制代码
from flask import Flask, request

app = Flask(__name__)

@app.route("/")
def index():
    # 不同级别的日志
    app.logger.debug("访问首页")
    app.logger.info("用户来自 IP: %s", request.remote_addr)
    app.logger.warning("检测到异常访问模式")
    app.logger.error("数据库连接失败")
    app.logger.critical("磁盘空间不足,服务即将中止")
    return "OK"

日志级别(由低到高)

级别 使用场景
DEBUG 开发调试时的详细信息,生产环境默认不输出
INFO 一般的运行信息,如请求记录、服务启动
WARNING 警告信息,潜在问题但不影响当前运行
ERROR 错误信息,某个功能出错但服务还在运行
CRITICAL 严重错误,可能导致服务停止

在Debug模式下,Flask的日志级别自动设为DEBUG。生产环境中应按需设置为INFOWARNING,避免输出太多无用信息。

5. 配置日志输出到文件

将日志写入文件,便于事后分析和排查:

复制代码
import logging
from logging.handlers import RotatingFileHandler

# 配置文件日志处理器——日志文件达到10MB后自动轮转
handler = RotatingFileHandler(
    "runoob_app.log",
    maxBytes=10 * 1024 * 1024,  # 单个文件最大10MB
    backupCount=5                # 保留最近5个备份
)

# 设置日志格式
handler.setFormatter(logging.Formatter(
    "[%(asctime)s] %(levelname)s in %(module)s: %(message)s"
))

# 将handler添加到Flask的logger
app.logger.addHandler(handler)
app.logger.setLevel(logging.INFO)

日志格式常用占位符

占位符 说明
%(asctime)s 时间戳
%(levelname)s 日志级别(INFO、ERROR等)
%(module)s 模块名
%(funcName)s 函数名
%(lineno)d 行号
%(message)s 日志消息

6. 捕获未处理的异常

使用@app.errorhandler(500)可以捕获未处理的异常并记录日志:

复制代码
import traceback

@app.errorhandler(500)
def internal_error(error):
    # 记录完整的异常堆栈
    app.logger.error("服务器内部错误:\n%s", traceback.format_exc())
    
    # 向用户显示友好的错误页面
    return """
    <h1>500 - 服务器内部错误</h1>
    <p>抱歉,服务器遇到了一个意外错误。我们已记录该问题,请稍后再试。</p>
    <p>如果持续出现此问题,请联系技术支持。</p>
    """, 500

7. 蓝图中的错误处理

蓝图也支持独立的错误处理器,只作用于该蓝图的路由:

复制代码
# auth.py
from flask import Blueprint, render_template

bp = Blueprint("auth", __name__)

@bp.errorhandler(404)
def auth_not_found(error):
    """auth蓝图专用的404错误页面"""
    return render_template("auth/404.html"), 404
注册方式 作用范围
@app.errorhandler 全局生效
@bp.errorhandler 仅在该蓝图路由中生效

8. 常见HTTP错误码速查

状态码 含义 常见原因
400 Bad Request 请求参数格式错误、缺少必要字段
401 Unauthorized 用户未登录或认证失败
403 Forbidden 用户已登录但没有访问权限
404 Not Found 资源(文章、用户等)不存在
405 Method Not Allowed 使用了错误的HTTP方法
429 Too Many Requests 请求频率超过限制
500 Internal Server Error 代码异常、数据库连接失败等未处理错误
502 Bad Gateway 代理服务器收到无效响应
503 Service Unavailable 服务暂时不可用

9. 错误处理最佳实践

实践 说明
自定义错误页面 使用@app.errorhandler覆盖默认错误页面,保持品牌一致性
记录错误日志 errorhandler中记录traceback,便于排查问题
区分客户端错误(4xx)和服务器错误(5xx) 前者返回提示信息,后者记录完整堆栈
使用环境变量控制日志级别 开发环境用DEBUG,生产环境用INFOWARNING
敏感信息脱敏 错误日志中不要记录密码、Token等敏感信息
在生产环境暴露堆栈 不要向用户显示完整的异常堆栈
忽略错误 每个abort()和可能抛异常的地方都应有对应的处理

小结

本章全面讲解了Flask的错误处理与日志机制。@app.errorhandler装饰器可自定义各类HTTP错误页面,支持状态码和异常类两种注册方式;视图函数中使用abort()主动触发错误并传递描述信息;日志通过app.logger记录,支持DEBUGCRITICAL五个级别,可配合RotatingFileHandler实现日志文件的自动轮转;traceback.format_exc()可捕获异常堆栈;蓝图也支持独立的错误处理器。完善的错误处理加上规范的日志记录,是打造健壮可靠Web应用的必备手段。

相关推荐
深念Y25 分钟前
浏览器缩放检测的前端通用方案
前端
2401_8906034026 分钟前
Python入门语法(一)
java·开发语言·python
烂蜻蜓32 分钟前
Flask入门教程(十六):中间件与扩展——增强应用功能的两种机制
python·中间件·flask
风骏时光牛马32 分钟前
AIAgent异常故障根因分析与复盘总结
前端
weixin_4316004433 分钟前
前端数据埋点(7):Web Vitals——页面慢不慢,不是再包一层 fetch
前端·性能优化·sentry·数据埋点
এ慕ོ冬℘゜2 小时前
前端实战:jQuery实现动态表格渲染与状态切换功能
前端·javascript·jquery
烂蜻蜓2 小时前
Flask入门教程(十二):表单处理——从基础到Flask-WTF完整实践
后端·python·flask
jay神3 小时前
【计算机毕业设计】基于Flask+Vue的电影数据可视化与智能推荐系统
前端·vue.js·python·信息可视化·flask·毕业设计·课程设计