FastAPI从入门到实战(12)——错误处理

2023-11-04

错误提示是非常重要的,比如权限控制、资源控制等场景,需要服务器返回给用户错误提示,包括状态码和提示等内容,所以本文就主要记录FastAPI里的错误处理相关的内容

抛出一个HTTPException

@app08.get("/stu08/{id}")
def stu08_get_error(
        id: str = Path(...)
):
    if id != "MinChess":
        return HTTPException(status_code=404, detail="not found")
    return {
        "name": "MinChess",
        "age": 22,
        "Blog": "https://blog.jiumoz.com"
    }

fastapi中导入HTTPException,并在路径操作函数中进行判断输出即可;

上面的代码就是当输入的id不为MinChess的时候抛出错误,错误代码为404,详细信息为not found

image-20221203164124803

添加自定义响应头

@app08.get("/stu08/header/{id}")
def stu08_get_error_header(
        id: str
):
    if id != "MinChess":
        raise HTTPException(
            status_code=404,
            detail="Not Found",
            headers={"X-Error": "There gose my error."}
        )
    return {
        "name": "MinChess",
        "age": 22,
        "Blog": "https://blog.jiumoz.com"
    }

有些场景的前端可能需要在HTTP的错误中添加一些自定义的响应头,添加方法如上,直接设置HTTPExceptionheaders即可;

image-20221203164434584

自定义异常处理器

定义一个Exception类型错误类UnicornException,在实际应用中就对应登录失败错误、验证码错误等;

class UnicornException(Exception):
    def __init__(self, name: str):
        self.name = name

在主应用中为UnicornException错误定义处理函数,如果没在同一个文件内,需要导入对应的类,参考文末的源码;

@app.exception_handler(exception.UnicornException) # 用@app.exception_handler() 为UnicornException添加自定义异常控制器
async def unicorn_exception_handler(request: Request, exc: exception.UnicornException):
    """
    :param request: 请求头
    :param exc: 异常对象
    :return:
    """
    print(f"全局自定义异常:method:{request.method} URL:{request.url}Headers:{request.headers}")
    return JSONResponse(
        status_code=418,
        content={
            "message": f"你输入的: {exc.name} 是错的!!!"
        }
    )

在应用中进行声明即可,要导入相关的类;

@app08.get("/stu08/custom/{name}")
async def stu08_custom(
        name: str = Path(default="MinChess")
):
    if name == "MinChess":
        raise UnicornException(name=name)
    return {"name": "MinChess"}

上面的函数就是当用户输入的name为MinChess的时候,抛出一个UnicornException错误;这里的错误处理函数要实现全局处理的话,就一定要挂载道主应用上;

根据上面的处理函数,我们操作输入MinChess的时候,不仅会返回给前端既定的数据,也会在控制台进行相关信息的输出,如下:

image-20221203164558523

image-20221203164641276

重写默认异常处理器

重写默认的异常处理器就是将fastapi内置的默认异常进行人为干预,方法很简单,同上面的方法,进行重写即可;

@app.exception_handler(RequestValidationError)  # 重写请求验证异常处理器
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    """
    请求参数验证异常
    :param request: 请求头信息
    :param exc: 异常对象
    :return:
    """
    # 日志记录异常详细上下文
    print(f"全局异常:{request.method}URL{request.url}Headers:{request.headers}{traceback.format_exc()}")
    return PlainTextResponse(str(exc), status_code=400)


@app.exception_handler(StarletteHTTPException)  # 重写HTTPException异常处理器
async def http_exception_handler(request, exc):
    print(f"全局异常:{request.method}URL{request.url}Headers:{request.headers}{traceback.format_exc()}")
    return PlainTextResponse(str(exc.detail), status_code=exc.status_code)

上面的第一个函数就是重写的参数校验的处理器,返回PlainTextResponse信息的同时会在控制台打印具体错误;

上面的第二个函数就是重写的HTTPException异常的处理器,同样返回PlainTextResponse信息的同时会在控制台打印具体错误;

  • 参数校验

这部分不需要重新写操作函数,找到之前写的某一个请求,发送错误类型的错误就会抛出异常:

image-20221203170053064

image-20221203170120577

image-20221203165215816

  • HTTPException
@app08.get("/stu08/Request_Validation_Error/{param}")
async def stu08_request_validation_error(param: int):
    if param != 2:
        raise HTTPException(detail="请输入MinChess!", status_code=410)
    return {"param": param}

新建一个请求,用本章第一个例子也可以,上面的代码就表示当输入的param不为2时,抛出HTTPException异常:

image-20221203164912237

image-20221203164845563

源码

项目结构如下图,具体的配置可以参看下面文章的第二节:

https://blog.jiumoz.com/archives/fastapi-cong-ru-men-dao-shi-zhan-13-chang-jian-pei-zhi-xiang

image-20221203163907997

  • exception.py
# -*- coding: utf-8 -*-
# @Time: 2022/12/2 16:28
# @Author: MinChess
# @File: exception.py
# @Software: PyCharm
class UnicornException(Exception):
    def __init__(self, name: str):
        self.name = name
  • main.py
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse, PlainTextResponse, HTMLResponse
from fastapi.exceptions import RequestValidationError
from fastapi.staticfiles import StaticFiles
from stu import app01, app02, app03, app04, app05, app06, app07, app08
import uvicorn
import traceback
from utils import exception # 导入类
from starlette.exceptions import HTTPException as StarletteHTTPException

app = FastAPI(
    # 创建一个FastAPI实例\这里的变量 app 会是 FastAPI 类的一个「实例」。\这个实例将是创建你所有 API 的主要交互对象。\这个 app 同样在命令中被 uvicorn 所引用:
    title='FastAPI学习教程文档——title',
    description='这是FastAPI教程的文档——description',
    version='1.0.0',
    docs_url='/docs',
    redoc_url='/redoc',
)

app.mount(path="/static", app=StaticFiles(directory='./static'), name='static')


@app.exception_handler(exception.UnicornException) # 用@app.exception_handler() 为UnicornException添加自定义异常控制器
async def unicorn_exception_handler(request: Request, exc: exception.UnicornException):
    """
    :param request: 请求头
    :param exc: 异常对象
    :return:
    """
    print(f"全局自定义异常:method:{request.method} URL:{request.url}Headers:{request.headers}")
    return JSONResponse(
        status_code=418,
        content={
            "message": f"你输入的: {exc.name} 是错的!!!"
        }
    )


@app.exception_handler(RequestValidationError)  # 重写请求验证异常处理器
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    """
    请求参数验证异常
    :param request: 请求头信息
    :param exc: 异常对象
    :return:
    """
    # 日志记录异常详细上下文
    print(f"全局异常:{request.method}URL{request.url}Headers:{request.headers}{traceback.format_exc()}")
    return PlainTextResponse(str(exc), status_code=400)


@app.exception_handler(StarletteHTTPException)  # 重写HTTPException异常处理器
async def http_exception_handler(request, exc):
    print(f"全局异常:{request.method}URL{request.url}Headers:{request.headers}{traceback.format_exc()}")
    return PlainTextResponse(str(exc.detail), status_code=exc.status_code)
  • stu08.py
# -*- coding: utf-8 -*-
# @Time: 2022/12/1 14:55
# @Author: MinChess
# @File: stu08.py
# @Software: PyCharm
from fastapi import APIRouter, HTTPException, Path,Body
from fastapi.exceptions import RequestValidationError
from fastapi.encoders import jsonable_encoder
from typing import Optional, List
from pydantic import Field
from utils import UnicornException
from pydantic import BaseModel
from datetime import datetime

app08 = APIRouter()


# 抛出HTTPException
@app08.get("/stu08/{id}")
def stu08_get_error(
        id: str = Path(...)
):
    if id != "MinChess":
        return HTTPException(status_code=404, detail="not found")
    return {
        "name": "MinChess",
        "age": 22,
        "Blog": "https://blog.jiumoz.com"
    }


# 添加自定义响应头
@app08.get("/stu08/header/{id}")
def stu08_get_error_header(
        id: str
):
    if id != "MinChess":
        raise HTTPException(
            status_code=404,
            detail="Not Found",
            headers={"X-Error": "There gose my error."}
        )
    return {
        "name": "MinChess",
        "age": 22,
        "Blog": "https://blog.jiumoz.com"
    }


# Theere id MinChess's python pro
# 自定义异常处理器

@app08.get("/stu08/custom/{name}")
async def stu08_custom(
        name: str = Path(default="MinChess")
):
    if name == "MinChess":
        raise UnicornException(name=name)
    return {"name": "MinChess"}


@app08.get("/stu08/Request_Validation_Error/{param}")
async def stu08_request_validation_error(param: int):
    if param != 2:
        raise HTTPException(detail="请输入MinChess!", status_code=410)
    return {"param": param}


感谢阅读!

九陌斋地址:https://blog.jiumoz.com/archives/fastapi-cong-ru-men-dao-shi-zhan-12-cuo-wu-chu-li

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FastAPI从入门到实战(12)——错误处理 的相关文章

  • Python BigQuery 存储。并行读取多个流

    我有以下玩具代码 import pandas as pd from google cloud import bigquery storage v1beta1 import os import google auth os environ G
  • Django REST序列化器:创建对象而不保存

    我已经开始使用 Django REST 框架 我想做的是使用一些 JSON 发布请求 从中创建一个 Django 模型对象 然后使用该对象而不保存它 我的 Django 模型称为 SearchRequest 我所拥有的是 api view
  • 如何在刻度标签和轴之间添加空间

    我已成功增加刻度标签的字体 但现在它们距离轴太近了 我想在刻度标签和轴之间添加一点呼吸空间 如果您不想全局更改间距 通过编辑 rcParams 并且想要更简洁的方法 请尝试以下操作 ax tick params axis both whic
  • InterfaceError:连接已关闭(使用 django + celery + Scrapy)

    当我在 Celery 任务中使用 Scrapy 解析函数 有时可能需要 10 分钟 时 我得到了这个信息 我用 姜戈 1 6 5 django celery 3 1 16 芹菜 3 1 16 psycopg2 2 5 5 我也使用了psyc
  • Pycharm Python 控制台不打印输出

    我有一个从 Pycharm python 控制台调用的函数 但没有显示输出 In 2 def problem1 6 for i in range 1 101 2 print i end In 3 problem1 6 In 4 另一方面 像
  • pandas 替换多个值

    以下是示例数据框 gt gt gt df pd DataFrame a 1 1 1 2 2 b 11 22 33 44 55 gt gt gt df a b 0 1 11 1 1 22 2 1 33 3 2 44 4 3 55 现在我想根据
  • 如何等到 Excel 计算公式后再继续 win32com

    我有一个 win32com Python 脚本 它将多个 Excel 文件合并到电子表格中并将其另存为 PDF 现在的工作原理是输出几乎都是 NAME 因为文件是在计算 Excel 文件内容之前输出的 这可能需要一分钟 如何强制工作簿计算值
  • Spark的distinct()函数是否仅对每个分区中的不同元组进行洗牌

    据我了解 distinct 哈希分区 RDD 来识别唯一键 但它是否针对仅移动每个分区的不同元组进行了优化 想象一个具有以下分区的 RDD 1 2 2 1 4 2 2 1 3 3 5 4 5 5 5 在此 RDD 上的不同键上 所有重复键
  • 为 pandas 数据透视表中的每个值列定义 aggfunc

    试图生成具有多个 值 列的数据透视表 我知道我可以使用 aggfunc 按照我想要的方式聚合值 但是如果我不想对两列求和或求平均值 而是想要一列的总和 同时求另一列的平均值 该怎么办 那么使用 pandas 可以做到这一点吗 df pd D
  • 从列表中的数据框列中搜索部分字符串匹配 - Pandas - Python

    我有一个清单 things A1 B2 C3 我有一个 pandas 数据框 其中有一列包含用分号分隔的值 某些行将包含与上面列表中的一项的匹配 它不会是完美的匹配 因为它在其中包含字符串的其他部分 该列 例如 该列中的一行可能有 哇 这里
  • python 集合可以包含的值的数量是否有限制?

    我正在尝试使用 python 设置作为 mysql 表中 ids 的过滤器 python集存储了所有要过滤的id 现在大约有30000个 这个数字会随着时间的推移慢慢增长 我担心python集的最大容量 它可以包含的元素数量有限制吗 您最大
  • HTTPS 代理不适用于 Python 的 requests 模块

    我对 Python 还很陌生 我一直在使用他们的 requests 模块作为 PHP 的 cURL 库的替代品 我的代码如下 import requests import json import os import urllib impor
  • 如何将 numpy.matrix 提高到非整数幂?

    The 运算符为numpy matrix不支持非整数幂 gt gt gt m matrix 1 0 0 5 0 5 gt gt gt m 2 5 TypeError exponent must be an integer 我想要的是 oct
  • Numpy 优化

    我有一个根据条件分配值的函数 我的数据集大小通常在 30 50k 范围内 我不确定这是否是使用 numpy 的正确方法 但是当数字超过 5k 时 它会变得非常慢 有没有更好的方法让它更快 import numpy as np N 5000
  • Python 3 中“map”类型的对象没有 len()

    我在使用 Python 3 时遇到问题 我得到了 Python 2 7 代码 目前我正在尝试更新它 我收到错误 类型错误 map 类型的对象没有 len 在这部分 str len seed candidates 在我像这样初始化它之前 se
  • Python:计算字典的重复值

    我有一本字典如下 dictA unit1 test1 alpha unit1 test2 beta unit2 test1 alpha unit2 test2 gamma unit3 test1 delta unit3 test2 gamm
  • 检查所有值是否作为字典中的键存在

    我有一个值列表和一本字典 我想确保列表中的每个值都作为字典中的键存在 目前我正在使用两组来确定字典中是否存在任何值 unmapped set foo set bar keys 有没有更Pythonic的方法来测试这个 感觉有点像黑客 您的方
  • 在python中,如何仅搜索所选子字符串之前的一个单词

    给定文本文件中的长行列表 我只想返回紧邻其前面的子字符串 例如单词狗 描述狗的单词 例如 假设有这些行包含狗 hotdog big dog is dogged dog spy with my dog brown dogs 在这种情况下 期望
  • 在 Python 类中动态定义实例字段

    我是 Python 新手 主要从事 Java 编程 我目前正在思考Python中的类是如何实例化的 我明白那个 init 就像Java中的构造函数 然而 有时 python 类没有 init 方法 在这种情况下我假设有一个默认构造函数 就像
  • Spark.read 在 Databricks 中给出 KrbException

    我正在尝试从 databricks 笔记本连接到 SQL 数据库 以下是我的代码 jdbcDF spark read format com microsoft sqlserver jdbc spark option url jdbc sql

随机推荐

  • Android中的ConstraintLayout约束布局

    ConstraintLayout约束布局 ConstraintLayout有啥好处呢 可以减少布局层次 特别适合复杂的大型布局 可谓是集线性布局和相对布局于一身的荣誉布局 使用 添加依赖 目前 AndroidStudio新的版本默认就给你上
  • MMdetection3D学习系列(二)——KITTI数据集训练测试及可视化

    安装完环境以后 就可以进行测试了 这里我使用的是KITTI数据集进行测试 关于KITTI数据集 网上有很多介绍了 这里简单说一下在mmdet3d中它需要的文件层级样式吧 主要是针对RGB和点云数据进行检测 一般来说采用其中一侧的彩色摄像头的
  • centos7重启或关机卡死

    这个问题其实是systemd219这个版本的问题 查看systemd版本 请使用systemctl version 由于systemd进程的判断比之前更加严格 如果某些进程不响应SIGTERM信号 可能会导致重启是挂死 该问题和业务进程对S
  • Ubuntu查看安装的软件、.开头的文件

    1 dpkg l grep 比如 dpkg l grep libjansson4 2 show hidden files那里
  • Spring整合mybatis和Junit单元测试

    1 Spring整合mybatis 前提了解 spring 管理 mybatis mybatis 管理 mapper 要依赖于德鲁伊连接池 spring 管理sqlsessionfactory 思路 Spring整合Mybatis主要做两件
  • Vue极简使用2

    Vue极简使用 Vue基础内容 模板语法 解析文本 解析原始HTML 动态属性 模板语法使用限制 条件渲染 列表渲染 事件处理 列表渲染 事件处理 修饰符 表单输入绑定 计算属性 样式处理 表单输入和绑定 修饰符 计算属性和监听器 计算属性
  • 差分详细讲解(C++)

    每日一句 平凡的我在人多的地方曾极力小心翼翼 但不知从何时起 我不太在意别人的目光了 比起被人觉得是个怪人 我现在更害怕浪费时间 差分 一 一维差分 二 二维差分 一 一维差分 差分就是前缀和的逆运算 如果你不懂什么是前缀和 看这里 gt
  • Ubuntu20.04下解决Qt出现qt.qpa.plugin:Could not load the Qt platform plugin “xcb“ 问题

    问题描述 python调用matplotlib pyplot库进行图形绘制时弹出错误提示 qt qpa plugin Could not load the Qt platform plugin xcb in even though it w
  • (个人)AR电子书系统创新实训第五周(1)

    服务器上传大文件的问题 在搭建并使用了云服务器后 我遇到了一个奇怪的问题 如果上传的文件中包含了视屏的话 上传就会失败 同时返回一个402error页面 一开始 我以为是文件类型的问题 通过网上查找后 我发现问题依然在于服务器本身的设置上
  • linux学习lesson14

    目录 1 df命令 2 du命令 3 磁盘分区 1 df命令 命令df disk filesystem的简写 用于查看已挂载磁盘的总容量 使用容量 剩余容量等 可以不加任何参数 默认以KB为单位显 i 表示查看inodes的使用状况 如已使
  • zookeeper环境构建

    关于zookeeper的作用这里不再作详述 相信很多开发人员在很多场景都使用zookeeper作为任务协调 1 安装jdk 这里不述详述 下载jdk压缩包 并在 etc profile中增加相关的环境变量配置 export JAVA HOM
  • python各个版本区别_Python 的各个版本

    Python 现在用的最多的就是两个版本 Python 2 x 系列 以及一个较新的 Python 3 x 系列 Python 3 x 系列是开始于2008年的十二月的 3 0 版本 从这个版本发布开始 Python 2 7 之后就只有小版
  • 解决Jetbrains旗下产品的插件下载失败问题(IntelliJ IDEA、RubyMine、WebStorm、PhpStorm、PyCharm、AppCode、Android Studio等)

    博主主要关注IntelliJ IDEA插件 使用时安装超时 解决办法其实很简单 进入Jetbrains官方插件仓库地址 https plugins jetbrains com 选择你所用的开发工具 然后在左上角搜索框搜索你需要的插件 搜索后
  • JDK1.8 之Stream API总结

    2019独角兽企业重金招聘Python工程师标准 gt gt gt Stream是 Java 8新增加的类 用来补充集合类 Stream代表数据流 流中的数据元素的数量可能是有限的 也可能是无限的 Stream和其它集合类的区别在于 其它集
  • mysql insert into多条_MySql中使用INSERT INTO语句更新多条数据的例子

    我们知道当插入多条数据的时候insert支持多条语句 复制代码 代码如下 INSERT INTO t member id name email VALUES 1 nick nick 126 com 4 angel angel 163 com
  • 如何解决:FileNotFoundError: 以及[Errno 2]No such file or directory

    出错原因 因为种种问题系统无法找到对应路径的文件 案例如下 我在pycharm的目录下新建了一个apple txt文件 想通过open 获取到对应文件里面的内容 结果提示 Errno 2 No such file or directory
  • Spark环境搭建部署全流程(Linux),看这一篇就够了

    前言 本篇文章将给各位展示如何快速地在linux上搭建spark 本文搭建的环境为Vmware 16 pro 下的CentOS 7 linux hadoop版本为3 x以上 Jdk1 8 以下是我总结出的spark几种模式的部署流程 如果是
  • 原来游戏技术行业最大的秘密竟然是...

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由腾讯游戏云发表于云 社区专栏 本篇文章主要是分享游戏业务面临的安全风险场景 以及基于这些场景的特点 我们应该如何做好对应的防护 一 背景 游戏行业DDoS攻击愈演愈烈 2017
  • Python模块multiprocessing & 实现多进程并发

    简介 multiprocessing模块是Python标准库中提供的一个用于实现多进程编程的模块 它基于进程而不是线程 可以利用多核CPU的优势 提高程序的执行效率 同时也可以实现进程间通信和数据共享 目录 1 参数说明 1 1 Proce
  • FastAPI从入门到实战(12)——错误处理

    错误提示是非常重要的 比如权限控制 资源控制等场景 需要服务器返回给用户错误提示 包括状态码和提示等内容 所以本文就主要记录FastAPI里的错误处理相关的内容 抛出一个HTTPException app08 get stu08 id de