Exception

在 Python 中,Exception 是所有内置异常的基类。通过继承 Exception,你可以创建自定义的异常类型,以便在代码中处理特定的错误情况。以下是对 Exception 的详细解释以及一些高级案例。

基本用法

创建自定义异常

你可以通过继承 Exception 来创建自定义异常类:

1
2
3
4
5
6
class MyCustomError(Exception):
def __init__(self, message: str):
self.message = message

def __str__(self):
return self.message

抛出自定义异常

在函数中,你可以使用 raise 关键字抛出自定义异常:

1
2
3
4
def divide(a: int, b: int) -> int:
if b == 0:
raise MyCustomError("Cannot divide by zero")
return a / b

捕获自定义异常

你可以使用 tryexcept 块来捕获并处理自定义异常:

1
2
3
4
try:
result = divide(10, 0)
except MyCustomError as e:
print(f"Caught an exception: {e}")

高级案例

1. 带有详细信息的自定义异常

你可以为自定义异常添加更多的属性,以便在捕获时提供更多的上下文信息:

1
2
3
4
5
6
7
class MyCustomError(Exception):
def __init__(self, message: str, code: int):
self.message = message
self.code = code

def __str__(self):
return f"Error {self.code}: {self.message}"

2. 使用自定义异常进行错误处理

在处理复杂逻辑时,你可以使用自定义异常来区分不同的错误类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class InvalidInputError(MyCustomError):
def __init__(self, message: str):
super().__init__(message, 400)

class InternalServerError(MyCustomError):
def __init__(self, message: str):
super().__init__(message, 500)

def process_data(data: str):
if not data:
raise InvalidInputError("Input data is empty")
try:
# 处理数据
pass
except Exception as e:
raise InternalServerError(f"An internal error occurred: {str(e)}")

3. 捕获多个自定义异常

你可以使用多个 except 块来捕获不同的自定义异常:

1
2
3
4
5
6
try:
result = divide(10, 0)
except InvalidInputError as e:
print(f"Invalid input: {e}")
except InternalServerError as e:
print(f"Internal server error: {e}")

总结

Exception 是 Python 中用于处理异常的基础类。通过创建自定义异常,你可以更好地控制错误处理逻辑,提高代码的可读性和可维护性。在处理复杂逻辑时,使用自定义异常可以更清晰地区分不同的错误类型,并为其提供详细的上下文信息。

HTTPException

HTTPException 是 FastAPI 中用于抛出 HTTP 错误的异常类。它允许你定义自定义的 HTTP 响应状态码和响应体,从而提供更灵活的错误处理机制。下面是关于 HTTPException 的详细解释:

基本用法

HTTPException 的基本用法如下:

1
2
3
4
5
6
7
8
9
10
from fastapi import FastAPI
from fastapi.exceptions import HTTPException

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id == 3:
raise HTTPException(status_code=418, detail="This item is a teapot")
return {"item_id": item_id}

在这个例子中,当 item_id 为 3 时,会抛出一个 HTTPException,状态码为 418(这是一个 HTTP 状态码,表示“我是一个茶壶”)。

参数

HTTPException 构造函数接受以下参数:

  • status_code:HTTP 状态码,例如 404、500 等。
  • detail:错误详情,通常是一个字符串,用于描述错误原因。
  • headers:一个字典,包含额外的 HTTP 响应头。

示例

以下是一些使用 HTTPException 的示例:

1. 抛出 404 错误

1
2
3
4
5
6
7
8
9
10
from fastapi import FastAPI
from fastapi.exceptions import HTTPException

app = FastAPI()

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

2. 抛出 400 错误并添加自定义头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from fastapi import FastAPI
from fastapi.exceptions import HTTPException

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id < 0:
raise HTTPException(
status_code=400,
detail="Item ID must be a positive integer",
headers={"X-Error": "Invalid-Item-ID"}
)
return {"item_id": item_id}

3. 抛出 500 错误并添加多个头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from fastapi import FastAPI
from fastapi.exceptions import HTTPException

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id == 999:
raise HTTPException(
status_code=500,
detail="Internal server error",
headers={
"X-Error": "Internal-Error",
"X-Internal-Error-Code": "500-001"
}
)
return {"item_id": item_id}

自定义异常处理

FastAPI 允许你自定义异常处理逻辑,以便在捕获到 HTTPException 时执行特定的操作。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import HTTPException

app = FastAPI()

@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
return JSONResponse(
status_code=exc.status_code,
content={"message": exc.detail}
)

@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id == 3:
raise HTTPException(status_code=418, detail="This item is a teapot")
return {"item_id": item_id}

在这个例子中,当捕获到 HTTPException 时,会返回一个 JSON 响应,而不是默认的 HTML 响应。

总结

HTTPException 是 FastAPI 中一个非常有用的工具,它允许你抛出自定义的 HTTP 错误,并控制响应的状态码、详情和头信息。通过自定义异常处理,你可以进一步优化错误处理逻辑,提高应用的健壮性和用户体验。

RequestValidationError

RequestValidationError 是 FastAPI 中用于处理请求验证错误的异常类。当请求中的数据不符合 OpenAPI 或 Pydantic 模型定义时,FastAPI 会抛出这个异常。通过捕获和处理 RequestValidationError,你可以向客户端返回详细的验证错误信息。

基本用法

RequestValidationError 通常在请求处理函数中自动抛出,但你也可以手动抛出它来处理特定的验证错误。以下是一个基本示例:

1
2
3
4
5
6
7
8
from fastapi import FastAPI, Query
from fastapi.exceptions import RequestValidationError

app = FastAPI()

@app.get("/items/")
async def read_items(q: str = Query(..., min_length=3)):
return {"q": q}

在这个例子中,如果 q 参数的长度小于 3,FastAPI 会自动抛出 RequestValidationError

自定义异常处理

你可以通过自定义异常处理来捕获和处理 RequestValidationError。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError

app = FastAPI()

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

@app.get("/items/")
async def read_items(q: str = Query(..., min_length=3)):
return {"q": q}

在这个例子中,当捕获到 RequestValidationError 时,会返回一个 JSON 响应,包含详细的验证错误信息。

参数

RequestValidationError 的主要属性是 errors,它是一个包含所有验证错误的列表。每个错误都是一个字典,包含以下字段:

  • loc:错误的位置,通常是一个元组,表示模型路径。
  • msg:错误消息,描述了验证失败的原因。
  • type:错误类型,表示验证失败的具体原因。

示例

以下是一些使用 RequestValidationError 的示例:

1. 抛出自定义验证错误

1
2
3
4
5
6
7
8
9
10
from fastapi import FastAPI, Query
from fastapi.exceptions import RequestValidationError

app = FastAPI()

@app.get("/items/")
async def read_items(q: str = Query(..., min_length=3)):
if len(q) < 3:
raise RequestValidationError([{"loc": ("query", "q"), "msg": "Query must be at least 3 characters long", "type": "string.min_length"}])
return {"q": q}

2. 捕获并处理验证错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError

app = FastAPI()

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

@app.get("/items/")
async def read_items(q: str = Query(..., min_length=3)):
if len(q) < 3:
raise RequestValidationError([{"loc": ("query", "q"), "msg": "Query must be at least 3 characters long", "type": "string.min_length"}])
return {"q": q}

总结

RequestValidationError 是 FastAPI 中一个非常有用的工具,它允许你捕获和处理请求验证错误,并向客户端返回详细的错误信息。通过自定义异常处理,你可以进一步优化错误处理逻辑,提高应用的健壮性和用户体验。