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。生产环境中应按需设置为INFO或WARNING,避免输出太多无用信息。

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,生产环境用INFO或WARNING
✅ 敏感信息脱敏 错误日志中不要记录密码、Token等敏感信息
❌ 在生产环境暴露堆栈 不要向用户显示完整的异常堆栈
❌ 忽略错误 每个abort()和可能抛异常的地方都应有对应的处理

小结

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

相关推荐
Da Da 泓25 分钟前
五子棋 Web 端测试用例报告
前端·网络·websocket·网络协议·测试用例·项目
quantdash_cc29 分钟前
如何验证历史行情的交易日期是否完整覆盖研究区间?
python·数据分析·pandas·量化交易·股票数据·quantdash
I Am a robert girl30 分钟前
当智能体学会“串通”:从长程交互中读懂涌现式合谋
python·多智能体系统·多智能体协作·llm agent·涌现式合谋·对齐问题·激励机制设计
云和数据.ChenGuang1 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
zxcvb1531 小时前
远程查看本地文档:一条轻量 Web 文件服务的工程化链路
前端·远程查看文档
niucloud-admin1 小时前
NIUCLOUD PHP SAAS上门家政使用文档:城市管理
java·前端·php
专注仿真2 小时前
线性回归和逻辑回归算法详解
开发语言·人工智能·python·大模型训练·控制算法
北岛贰2 小时前
啵啵音乐迎来全新升级!
前端
wflynn3 小时前
GitHub 今日推荐|Edge0:让大号 MoE 模型在一台 Mac 上流式跑起来
python·开源·github
2601_967980113 小时前
python之用scapy分层解析pcap报文(Ethernet帧、IP数据包、TCP数据包、UDP数据包、Raw数据包)
python·scapy·pcap·协议分析·网络数据包