首页 > 编程问答 >FastAPI - 如何处理 websocket 端点中的通用异常

FastAPI - 如何处理 websocket 端点中的通用异常

时间:2024-07-25 14:55:58浏览次数:10  
标签:python websocket error-handling fastapi

我想了解在 FastAPI 应用程序中处理 websocket 端点异常的推荐方法是什么。

我尝试过:

app.add_exception_handler(Exception, handle_generic_exception)

它捕获 Exception ,但它没有捕获,例如 ValueError | ||我也尝试过使用

但它似乎不适用于 websocket。 @app.middleware("http") 你们中的任何人都知道处理 websocket 端点的

from fastapi import FastAPI, Request, Response, WebSocket

app = FastAPI()


app.add_exception_handler(AppException, handle_disconnect)

@app.middleware("http")
async def generic_exception_middleware(request: Request | WebSocket, call_next):
    try:
        return await call_next(request)
    except Exception as exc:
        send_something_to_client()
        print("some exception")


@app.websocket("/ws")
async def ws(websocket: WebSocket):
    raise ValueError("foo")

通用 异常的正确方法是什么吗? |编辑 2024-05-28: 我终于添加了装饰器来处理我的 websocket 端点的异常。但如果有任何更优雅的解决方案,请告诉我!

EDIT 2024-05-28:

I finally added the decorator for handling exceptions for my websocket endpoints. But if there is any more elegant solution, please let me know!

def handle_exceptions(func):
    """Decorator for handling exceptions."""

    @functools.wraps(func)
    async def wrapper(websocket: WebSocket):
        try:
            await func(websocket)
        except WebSocketDisconnect as exc:
            raise exc
        except AppError as exc:
            await app_error_handler(websocket, exc)
        except Exception as exc:  # pylint: disable=broad-exception-caught
            await generic_exception_handler(websocket, exc)

    return wrapper

[...]

@handle_exceptions
async def accept_api_v1(websocket: WebSocket):
    """Handle api v1 request."""
    await websocket.accept()
    do_things()

@app.websocket("/api/v1")
async def ws_api(websocket: WebSocket):
    """API v1 endpoint"""
    await accept_api_v1(websocket)

你对于使用中间件处理 FastAPI WebSocket 端点中的异常的理解是正确的,它们不适用于此场景。中间件主要用于处理 HTTP 请求和响应。

在 WebSocket 端点中,你需要在函数内部处理异常。以下是一些你可以采取的方法:

1. 使用 try-except 块:

这是处理 WebSocket 端点异常最直接的方法。你可以在你的 WebSocket 函数内部使用 try-except 块来捕获和处理异常。

@app.websocket("/ws")
async def ws(websocket: WebSocket):
    await websocket.accept()
    try:
        # 处理 WebSocket 消息
        while True:
            data = await websocket.receive_text()
            # 处理数据并可能引发异常
            if data == "raise":
                raise ValueError("Invalid data received")
            await websocket.send_text(f"Message received: {data}")
    except ValueError as e:
        await websocket.send_text(f"Error: {e}")
    except Exception as e:
        await websocket.send_text(f"An unexpected error occurred: {e}")
    finally:
        await websocket.close()

2. 使用装饰器来处理异常:

你可以创建一个装饰器来处理 WebSocket 函数中的异常,从而避免在每个函数中都编写 try-except 块。

from functools import wraps

def websocket_exception_handler(func):
    @wraps(func)
    async def wrapper(websocket: WebSocket):
        await websocket.accept()
        try:
            await func(websocket)
        except Exception as e:
            await websocket.send_text(f"An error occurred: {e}")
        finally:
            await websocket.close()
    return wrapper

@app.websocket("/ws")
@websocket_exception_handler
async def ws(websocket: WebSocket):
    # 处理 WebSocket 消息
    while True:
        data = await websocket.receive_text()
        if data == "raise":
            raise ValueError("Invalid data received")
        await websocket.send_text(f"Message received: {data}")

3. 自定义异常处理类:

你可以定义自定义异常类,并在 try-except 块中使用它们来处理特定类型的异常。

class WebSocketError(Exception):
    def __init__(self, message, status_code):
        super().__init__(message)
        self.status_code = status_code

@app.websocket("/ws")
async def ws(websocket: WebSocket):
    await websocket.accept()
    try:
        # 处理 WebSocket 消息并可能引发异常
    except ValueError as e:
        await websocket.send_text(f"Error: {e}")
        await websocket.close(code=1002)  # 使用合适的关闭代码
    except WebSocketError as e:
        await websocket.send_text(f"Error: {e}")
        await websocket.close(code=e.status_code)

使用哪种方法取决于你的应用程序的具体需求。

请记住,在处理 WebSocket 端点中的异常时,向客户端发送有意义的错误消息非常重要,以便他们了解发生了什么。 你还可以使用不同的 WebSocket 关闭代码来表示错误的原因.

标签:python,websocket,error-handling,fastapi
From: 78527617

相关文章

  • 在 Python 中动态定义文字字符串排列的并集
    我有一个字符串列表:strings=['a','b','c']我想声明列表中所有可能的有序对的Union类型。硬编码,这看起来像:Literal我如何动态定义CustomType=Literal['ab','ac','aa','ba','bb','bc�......
  • 关于 Python 中装饰器缓存的困惑
    我正在使用Python装饰器来实现函数的缓存。我了解缓存结果以提高性能的基本概念,但我正在努力解决如何处理不同的函数参数并确保底层数据更改时缓存更新。我已经实现了一个基本装饰器,它将函数结果存储在基于参数的字典。但是,此方法无法处理函数参数可能具有复杂结构(如嵌套列......
  • Python:__add__ 和 +,浮点数和整数的不同行为
    当将整数值添加到浮点值时,我意识到如果在浮点上调用该方法可以正常工作,例如:__add__但如果在整数上调用则不行:>>>n=2.0>>>m=1>>>n.__add__(m)3.0起初我认为|||只是对>>>m.__add__(n)NotImplemented和__add__类型的实现方式不同(例如f......
  • python中scrapy爬取数据get()与getall()区别
    在使用scrapy进行爬取数据的时候,有些时候需要爬取的是一段文本,或者一个div里面有很多内容,这时候我们就要使用到get()或者getall()来获取数据: get():是获取的满足条件的第一个数据。getall():是获取的满足条件的所有数据。scrapyget()getall()原理在Scrapy中,get(......
  • python—NumPy基础(3)
    文章目录算术函数算术函数的使用算术函数中out参数的使用mod()函数的使用统计函数power()函数的使用median()函数的使用mean()函数的使用函数的使用其他常用函数tile()和repeat()函数的使用roll()函数的使用resize()函数的使用replace()和put()函数的使savetxt()和lo......
  • Python爬虫:代理ip电商数据实战
    引言:数据访问管理引发的烦恼作为一名Python博主,爬虫技能对于获取和分析数据至关重要,经常爬一下,有益身心健康嘛。爬虫技术对很多人来说,不仅仅是一种工具,更像是一种艺术,帮助我们从互联网中,捕捉到有价值的信息。我经常就会用爬虫来爬取一些所需的数据,用来进行数据分析和模型训......
  • python科学计算:加速库numba —— 安装和试用
    安装(anaconda环境下)condainstallnumbaDemo代码:fromnumbaimportjitfromnumpyimportarangeimportnumpyimporttime@jitdefsum2d(arr):M,N=arr.shaperesult=0.0foriinrange(M):forjinrange(N):result+=a......
  • Python - Selenium抓取淘宝直播间评论(可使用无头模式)
    Python-Selenium抓取淘宝直播间评论(可使用无头模式)下面介绍如何使用python中的selenium简单抓取淘宝直播间实时评论。友情提醒,仅供学习交流使用,请勿用于非法用途!一、创建python项目1.在目录下新建main.py和venv虚拟环境:创建虚拟环境:python-mvenvvenv激活虚拟环......
  • 需要帮助来提取此 XML 节点 - Python 中的 Excel 连接字符串
    我有一个Python程序,打开Excel(XLSX)文件,并尝试查找<connection>节点。这是connections.xml文件中的完整XML。<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?><connectionsxmlns="http://schemas.op......
  • 【python】Python中采集Prometheus数据,进行数据分析和可视化展示
    ✨✨欢迎大家来到景天科技苑✨✨......