前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >高效优雅处理程序错误实战

高效优雅处理程序错误实战

作者头像
python编程从入门到实践
修改2021-03-29 11:39:02
8550
修改2021-03-29 11:39:02
举报
文章被收录于专栏:python编程军火库

/ python 生产实战 高效优雅处理程序错误 /

今天,讨论一下程序中的错误处理。也许你会觉得这个事没什么意思,处理错误的代码并不难写。但你想过没有,要把错误处理写好,并不是件容易的事情。另外,任何一个稳定的程序中都会有大量的代码在处理错误,所以说,处理错误是程序中一件比较重要的事情。本篇我们系统地了解一下错误处理的各种方式和相关实践。

错误是指导致系统不能按照用户意图工作的一切原因、事件。在程序设计过程中,由于某些错误的存在,致使程序无法正常运行,处理这些错误以使程序正确运行就称为错误处理。错误处理功能是衡量编译器性能的重要方面,它在帮助程序员尽快修改程序方面起到了非常重要的作用。

1

程序错误类型

1.1

语法错误

语法错误是因为源程序中不正确的代码产生的,即在编写程序时没有遵守语法(或词法)规则,书写了错误的语法代码,从而导致编译器无法正确解释源代码而产生的错误,通常是由于录入的错误引起的,它在词法分析或语法分析时检测出来。如“非法字符”、“括号不匹配”、“缺少;”之类的错误。

1.2

语义错误

语义错误是指源程序中不符合语义规则的错误,即一条语句试图执行一条不可能执行的操作而产生的错误。语义错误有的在语义分析时检测处来,有的在运行时才能检测出来。如变量声明错误、作用域错误、数据存储区的溢出等错误。

1.3

逻辑错误

逻辑错误是指程序的运行结果和程序员的设想有出入时产生的错误。这类错误并不直接导致程序在编译期间和运行期间出现错误,但是程序未按预期方式执行,产生了不正确的运行结果,较难发现。这种错误只能通过分析结果,将结果与设计方案进行对比来发现。

2

HTTPException

我们用 HTTPException 模块返回带错误信息的 Response。HTTPException 是一个普通的 Python 异常,同时带有与 API 访问有关的附加数据。

代码语言:javascript
复制
from fastapi import FastAPI, HTTPException

app = FastAPI()

items = {"book": "Learn Python"}


@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]}

3

添加自定义头信息

有时候针对 HTTP 错误,在一些场景下,我们需要添加自定义头信息

我们可以在 云服务器

上来部署代码进行测试验证如下的代码:

代码语言:javascript
复制
from fastapi import FastAPI, HTTPException

app = FastAPI()

items = {"book": "Learn Python"}


@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": "error info"},

        )
    return {"item": items[item_id]}

4

自定义异常处理器

在 fastapi 中借助 the same exception utilities from Starlette,我们可以添加自定义异常处理器。假设我们有个自定义异常 UnicornException,我们想在全局范围内处理这个异常。借助 @app.exception_handler(),就可以实现我们的目标。

代码语言:javascript
复制

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

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

app = FastAPI()

@app.exception_handler(UnicornException)
async def unicorn_exception_handler(request: Request, exc: UnicornException):

    return JSONResponse(
        status_code=418,
        content={"message": f"Oops! {exc.name} did something. error"},
    )

@app.get("/get_name_info/{name}")
async def read_unicorn(name: str):
    if name == "haishiniu":
        raise UnicornException(name=name)

    return {"name": name}

5

重写缺省异常处理器

fastapi 有一些缺省的异常处理器。当我们抛出 HTTPException 异常或者当请求有非法数据的时候,这些处理器负责返回默认的 JSON 结果。我们可以重写这些异常处理器。

5.1

重写请求校验异常处理器

当一个请求包含非法数据的时候,fastapi 内部会抛出 RequestValidationError 异常,并且有默认的异常处理器来处理。我们可以用 @app.exception_handler(RequestValidationError) 来重写这个异常处理器。

代码语言:javascript
复制

from fastapi import FastAPI, HTTPException
from fastapi.exceptions import RequestValidationError
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.exception_handler(RequestValidationError)

async def validation_exception_handler(request, exc):
    return PlainTextResponse(str(exc), status_code=400)


@app.get("/items/{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}

5.2

重写 HTTPException 异常处理器

同样的方法,我们可以重写 HTTPException 异常处理器。例如,你可能想返回纯文本格式而不是 JSON 格式的错误信息。

代码语言:javascript
复制
from fastapi import FastAPI, HTTPException
from fastapi.exceptions import RequestValidationError
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.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    return PlainTextResponse(str(exc), status_code=400)


@app.get("/items/{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}

5.3

重用缺省异常处理器

我们可以导入并且重用缺省的异常处理器。我们从 fastapi.exception_handlers 导入缺省异常处理器。

代码语言:javascript
复制
from fastapi import FastAPI, HTTPException
from fastapi.exception_handlers import (
    http_exception_handler,
    request_validation_exception_handler,
)

from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException

app = FastAPI()

@app.exception_handler(StarletteHTTPException)
async def custom_http_exception_handler(request, exc):
    print(f"OMG! An HTTP error!: {repr(exc)}")
    return await http_exception_handler(request, exc)


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    print(f"OMG! The client sent invalid data!: {exc}")
    return await request_validation_exception_handler(request, exc)



@app.get("/items/{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}

在示例中,我们在抛出异常之前添加了一条日志输出。我们可以根据业务需求灵活的重用缺省异常处理器。

6

fastapi HTTPException 对比 Starlette HTTPException

fastapi 中 HTTPException 继承自 Starlette 的 HTTPException。 唯一的区别 fastapi 中 HTTPException 允许你在 response 添加头信息。主要在内部用于 OAuth 2.0 以及一些安全相关的功能。 因此,通常我们在代码中抛出 fastapi 的 HTTPException 异常。但是,当我们注册异常处理器的时候,我们应该注册为 Starlette 的 HTTPException。这样,当 Starlette 的内部代码或者 Starlette 扩展插件抛出 Starlette HTTPException 时,我们的处理器才能正常捕获和处理这个异常。如果我们要在代码中同时使用这两个类,为了避免命名冲突,我们可以重命名其中一个类。

7

总结

1.介绍了 什么是错误以及错误的分类信息

2.在 fastapi 中是如何自定义异常处理

原创不易,只愿能帮助那些需要这些内容的同行或刚入行的小伙伴,你的每次 点赞、分享 都是我继续创作下去的动力,我希望能在推广 python 技术的道路上尽我一份力量,欢迎在评论区向我提问,我都会一一解答,记得一键三连支持一下哦!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python编程从入门到实践 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档