【Python开发】FastAPI 06:处理错误

news2024/12/24 0:31:00

某些情况下,有必要向客户端(包括前端浏览器、其他应用程序、物联网设备等)返回错误提示,以便客户端能够了解错误的类型,从而做出应对。

目录

1 默认处理

1.1 错误介绍

1.2 使用 HTTPException

2 自定义处理

2.1 自定义响应头

2.2 自定义异常处理器

2.3 覆盖默认异常处理器

① 覆盖请求验证异常

② 覆盖 HTTPException 错误处理器

③ 使用 RequestValidationError 的请求体


📌源码地址:

https://gitee.com/yinyuu/fast-api_study_yinyu

1 默认处理

1.1 错误介绍

以下场景需要向客户端返回错误提示:

  • 客户端没有执行操作的权限
  • 客户端没有访问资源的权限
  • 客户端要访问的项目不存在
  • 等等 ...

遇到这些情况时,通常要返回 4XX(400 至 499)HTTP 状态码。 4XX 状态码与表示请求成功的 2XX(200 至 299) HTTP 状态码类似。

4XX 状态码表示客户端发生的错误,大家都知道「404 Not Found」错误吧~

1.2 使用 HTTPException

向客户端返回 HTTP 错误响应,可以使用 HTTPException

📌代码

from fastapi import FastAPI, HTTPException #导入 HTTPException

app = FastAPI()

items = {"yinyu": "The Foo Wrestlers"}

@app.get("/items/{item_id}")
async def read_item(item_id: str):
    if item_id not in items:
        raise HTTPException(status_code=404, detail="Item not found")
    return {"item": items[item_id]}

HTTPException 是额外包含了和 API 有关的常规 Python 异常,因为是 Python 异常,所以不能 return,只能 raise

📌响应结果

本例中,客户端用 ID 请求的 item 不存在时,触发状态码为 404 的异常:

比如,此时请求为 127.0.0.1:8000/items/yinyu(item_id 为 「yinyu」)时,客户端会接收到 HTTP 状态码 - 200 及如下 JSON 响应结果:

{
    "item": "The Foo Wrestlers"
}

但如果客户端请求 127.0.0.1:8000/items/bar(item_id bar」 不存在时),则会接收到 HTTP 状态码 - 404(「未找到」错误)及如下 JSON 响应结果:

{
    "detail": "Item not found"
}

触发 HTTPException 时,可以用参数 detail 传递任何能转换为 JSON 的值,不仅限于 str。 还支持传递 dictlist 等数据结构。FastAPI 能自动处理这些数据,并将之转换为 JSON

2 自定义处理

2.1 自定义响应头

一般情况下不会需要在代码中直接使用响应头,但是有时出于某些方面的安全需要,可能需要添加自定义响应头:

...

@app.get("/items-header/{item_id}")
async def read_item_header(item_id: str):
    if item_id not in items:
        raise HTTPException(
            status_code=404,
            detail="Item not found",
            headers={"X-Error": "There goes my error"} #添加自定义响应头
        )
    return {"item": items[item_id]}

也就是说,触发 HTTPException 时,响应头也会自定义返回~

2.2 自定义异常处理器

假设要触发的自定义异常叫作 SelfDefinedException, 且需要 FastAPI 实现全局处理该异常。

此时,可以用 @app.exception_handler() 添加自定义异常控制器:

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

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

@app.exception_handler(SelfDefinedException)
async def defined_exception_handler(request: Request, exc: SelfDefinedException):
    return JSONResponse(
        status_code=418,
        content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."},
    )

@app.get("/self_defined/{name}")
async def read_defined(name: str):
    if name == "yolo":
        raise SelfDefinedException(name=name)
    return {"unicorn_name": name}

请求 /self_defined/yolo 时,路径操作会触发 SelfDefinedException,且该异常将会被 defined_exception_handler处理。

接收到的错误信息清晰明了,HTTP 状态码为 418JSON 内容如下:

{"message": "Oops! yolo did something. There goes a rainbow..."}

2.3 覆盖默认异常处理器

FastAPI 自带了一些默认异常处理器,触发 HTTPException 或请求无效数据时,这些处理器返回默认的 JSON 响应结果, 当然你也可以使用自定义处理器覆盖默认异常处理器。

① 覆盖请求验证异常

请求过程中,若请求包含无效数据则 FastAPI 内部会触发 RequestValidationError。 该异常内置了默认异常处理器,覆盖默认异常处理器时需要导入 RequestValidationError,并用 @app.excption_handler(RequestValidationError) 装饰异常处理器。

这样,异常处理器就可以接收 Request 与异常。

from fastapi import FastAPI, HTTPException
from fastapi.exceptions import RequestValidationError
from fastapi.responses import PlainTextResponse

app = FastAPI()

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    return PlainTextResponse(str(exc), status_code=400)

@app.get("/items2/{item_id}")
async def read_item(item_id: int):
    if item_id == 3:
        raise HTTPException(status_code=418, detail="Nope! I don't like 3.")
    return {"item_id": item_id}

访问 http://127.0.0.1:8000/items2/yinyu,可以看到以下文本格式的错误信息:

并且替换了以下默认 JSON 错误信息:

{
    "detail": [
        {
            "loc": [
                "path",
                "item_id"
            ],
            "msg": "value is not a valid integer",
            "type": "type_error.integer"
        }
    ]
}

② 覆盖 HTTPException 错误处理器

同理,也可以覆盖 HTTPException 处理器。

例如,只为错误返回纯文本响应,而不是返回 JSON 格式的内容:

from fastapi import FastAPI, HTTPException
from fastapi.responses import PlainTextResponse
from starlette.exceptions import HTTPException as StarletteHTTPException

app = FastAPI()

@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
    return PlainTextResponse(str(exc.detail), status_code=exc.status_code)

@app.get("/items3/{item_id}")
async def read_item(item_id: int):
    if item_id == 3:
        raise HTTPException(status_code=418, detail="Nope! I don't like 3.")
    return {"item_id": item_id}

③ 使用 RequestValidationError 的请求体

RequestValidationError 包含其接收到的无效数据请求的 body 。

开发时,可以用这个请求体生成日志、调试错误,并返回给用户!!

from fastapi import FastAPI, Request, status
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel

app = FastAPI()

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}),
    )

class Item(BaseModel):
    title: str
    size: int

@app.post("/items4/")
async def create_item(item: Item):
    return item

现在试着发送一个无效的 item,例如:

{
  "title": "towel",
  "size": "XL"
}

收到的响应包含 body 信息,并说明数据是无效的:

{
  "detail": [
    {
      "loc": [
        "body",
        "size"
      ],
      "msg": "value is not a valid integer",
      "type": "type_error.integer"
    }
  ],
  "body": {
    "title": "towel",
    "size": "XL"
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/606379.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

论旅行之收获2

论旅行之收获2 概况站点第一站:北京市大兴区大兴机场基本情况吐槽小小趣事 第二站:云南省昆明长水机场云南省昆明市五华区基本概况经济分析 第三站:昆明站大理站云南省大理白族自治州大理市下关基本情况 第四站:云南省大理白族自治…

操作系统-进程和线程-处理机调度

目录 一、调度的概念 1.1调度的层次 1.1.1高级调度(作业调度) 1.1.2中级调度(内存调度) 1.1.3低级调度(进程调度) 1.2状态模型 1.3调度的时机 1.4调度方式 1.5进程的切换与过程 二、调度算法的评价指标 2.1CPU利用率 2.2吞吐量 2.3周转时间 2.4带权周转时间 2.5等…

Ansible基础6——文件模块、jinja2模板

文章目录 一、常用文件模块1.1 blockinfile模块1.2 file模块1.2.1 创建文件并赋予权限1.2.2 创建目录并赋予权限1.2.3 创建软连接1.2.4 删除文件或目录 1.3 fetch模块1.4 lineinfile模块1.5 stat模块1.6 synchronize模块 二、jinja2模板2.1 构建jinja2模板2.2 管理jinja2模板2.…

LVGL学习(1):中文字体的转换和汉字显示

在使用LVGL的过程中,我们难免需要显示汉字,所以这篇文章就来介绍一下如何转换中文汉字并成功显示到LVGL中。 文章目录 1 字体转换1.1 GUI Guider自动转换1.2 在线转换 2 字体的使用 1 字体转换 1.1 GUI Guider自动转换 打开GUI Guide,创建…

SAP-MM-批次删除归档操作

对于物料主数据的批次管理,一旦一个物料设置了批次管理,并已经产生了业务数据,但是发现当初业务主数据搞错了,此物料不需要在SAP系统进行批次管理,是否就无法取消其批次管理了呢,因为如果要取消此批次管理&…

Java: 字符集详解

1.计算机的存储规则 在计算机中,任意数据都是以二进制的形式来存储的。 每一个二进制数表示的0,1被称为比特位,8个比特位组成一个字节。 字节:计算机最小的存储单元。 2.ASCII字符集 用于存储英文字符,查询制定AS…

阿里云服务器开通全部端口流程

阿里云服务器端口怎么全部打开?在安全组中开启端口号,在安全组中把端口范围设置为-1/-1,授权对象填0.0.0.0/0,即可开通全部端口号,阿腾云来详细说下阿里云服务器端口全部打开教程: 阿里云服务器端口全部开…

结题报告范文

结题报告范文篇一 项目名称:__________ 项目编号: 项目负责人:_________ 专业年级:__________ 所在学院:__________ 起止年月: 电 话:__________ E-mail: 填表时期: 福建…

Vue基础入门(下)

<script src"https://unpkg.com/vuenext"></script> mixin混入&#xff08;局部使用&#xff09; 定义mixin对象 <script>// mixin 混入const mymixin{data(){return {number:2,count:1}},created(){console.log(mymixin created);},methods:{…

【Unity3D】Bloom特效

1 Bloom 特效原理 Bloom 特效是指&#xff1a;将画面中较亮的区域向外扩散&#xff0c;造成一种朦脓的效果。实现 Bloom 特效&#xff0c;一般要经过 3 个阶段处理&#xff1a;亮区域检测、高斯模糊、Bloom 合成。 本文完整资源见→Unity3D Bloom 特效。 1&#xff09;亮区域检…

OS-内存管理1- 4种基本管理方式(连续分配,页式,段式,段页)。

一&#xff0c;内存管理四种方式。 二&#xff0c;连续分配管理方式。 连续分配方式&#xff1a;为用户分配连续的内存空间。 1.单一连续分配方式 2.固定分区分配方式 3.动态分区分配方式 4.三种连续分配方式的对比。 三&#xff0c;基于页式存储管理。 1.页式 为进一步提高…

嵌入式系统中I2C总线通信基本方法

将 I2C spec 文章总结为一篇&#xff0c;目录如下 I2C Introduction I2C Architecture I2C Transfer I2C Synchronization And Arbitration I2C Hs-mode1、I2C Introduction 1、I2C 历史 I2C&#xff1a;Inter-Integrated Circuit&#xff0c;集成电路总线。 I2C 是 Philips…

部分网络结构记录

CVPR 2022 | Mobile-Former来了&#xff01;微软提出&#xff1a;MobileNetTransformer轻量化并行网络 文章链接: CVPR 2022 | Mobile-Former来了&#xff01;微软提出&#xff1a;MobileNetTransformer轻量化并行网络 - 知乎 (zhihu.com) Mobile-Former架构图 Mobile-Form…

Mybatis学习笔记一

目录 一、Mybatis特性二、快速入门1.导入依赖2.mybatis-config.xml配置3.创建mapper接口4.创建MyBatis的映射文件5.通过junit测试功能 三、MyBatis获取参数值的两种方式&#xff08;重点&#xff09;1.单个字面量类型的参数2.多个字面量类型的参数3.map集合类型的参数4.实体类类…

【六一特别文章】Python编写一个六一儿童节问答小游戏及趣味比赛

随着六一儿童节的到来&#xff0c;我们可以为孩子们编写一个有趣的小游戏&#xff0c;让他们在游戏中学习有关六一儿童节的知识。本文将介绍如何用Python编写一个六一儿童节问答小游戏及趣味比赛。 首先&#xff0c;我们需要准备一些有关六一儿童节的问题和答案。这里我准备了…

云原生之docker详解

目录 1.云原生概念 1.1 云原生定义 1.2 云原生元素 1.2.1 微服务 1.2.2 DevOps 1.2.3 持续交付 1.2.4 容器化 2. Docker 2.1 Docker概述 2.1.1 Docker 定义 2.1.2 Docker应用场景 2.1.3 Docker的架构 2.2 Docker命令 2.2.1 docker进程相关命令 2.2.2 docker镜像…

htmlCSS-----CSS选择器(下)

目录 前言&#xff1a; 2.高级选择器 &#xff08;1&#xff09;子代选择器 &#xff08;2&#xff09;伪类选择器 &#xff08;3&#xff09;后代选择器 &#xff08;4&#xff09;兄弟选择器 相邻兄弟选择器 通用兄弟选择器 &#xff08;5&#xff09;并集选择器 &am…

测试进阶必备,这5款http接口自动化测试工具真的很香

现在市场上能做接口自动化测试的工具有很多&#xff0c;一搜一大把&#xff0c;让人眼花缭乱。我们去选择对应实现方式时&#xff0c;不管是框架体系还是成熟稳定的工具&#xff0c;核心目的都是期望引入的技术能在最低投入的情况下达到最优效果。 那么我们选择依据出来了&…

LearnOpenGL-高级OpenGL-9.几何着色器

本人初学者&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 文章目录 几何着色器使用几何着色器造几个房子爆破物体法向量可视化 几何着色器 简介 在顶点和片段着色器之间有一个可选的几何着色器几何着色器的输入是一个图元&#xff08;如点或三角形&#xff09;的一…

【02】STM32·HAL库开发-Cortex-M系列介绍 | Cortex内核分类及特征 | Cortex-M3/M4/M7介绍

目录 1.ARM公司&#xff08;了解&#xff09;2.Cortex内核分类及特征&#xff08;了解&#xff09;3.Cortex-M3/4/7介绍&#xff08;了解&#xff09; 1.ARM公司&#xff08;了解&#xff09; ARM的R是RISC&#xff08;精简指令集计算机&#xff09;的缩写。ARM公司只做内核设计…