10. 에러 처리
에러를 처리하기 위해서 보통 try, except문을 사용한다. 하지만 에러가 발생하는 모든 상횡에 대해 try문을 작성하는것은 비효율적이다.
HTTPException 사용하여 에러 내기
from fastapi import FastAPI, HTTPException, status
app = FastAPI()
users = {
1: {"name": "Hi"},
2: {"name": "Hello"},
3: {"name": "안녕"},
}
@app.get("/users/{user_id}")
async def get_user(user_id: int):
if user_id not in users.keys():
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"<User: {user_id}> is not exists.",
)
return users[user_id]
HTTPException을 이용하면 detail로 상세한 에러 정보를 알려줄 수 있지만 서버나 클라이언트 딴에서도 이 detail 문을 확인해야 에러 정보를 확인할 수 있기 때문에 좋은 방법은 아니다. 그래서 보통은 사용자 정의 에러를 만든다.
사용자 정의 에러
사용자 정의 에러를 만들기 위해서는 Exception 클래스를 상속받아야 한다.
from fastapi import FastAPI
app = FastAPI()
class SomeError(Exception):
def __init__(self, name: str, code: int):
self.name = name
self.code = code
def __str__(self):
return f"<{self.name}> is occured. code: <{self.code}>"
app = FastAPI()
@app.get("/error")
async def get_error():
raise SomeError("Hello", 511)
위에서 확인할 수 있는 에러 코는 500으로 서버에서 에러가 났기 때문에 클라이언트는 어디서 에러가 일어났는지 모른다. 따라서 아래와 같이 에러를 처리할 핸들러를 만든다.
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
class SomeError(Exception):
def __init__(self, name: str, code: int):
self.name = name
self.code = code
def __str__(self):
return f"<{self.name}> is occured. code: <{self.code}>"
app = FastAPI()
@app.exception_handler(SomeError)
async def some_error_handler(request: Request, exc: SomeError):
return JSONResponse(
content={"message": f"error is {exc.name}"}, status_code=exc.code
)
@app.get("/error")
async def get_error():
raise SomeError("Hello", 511)
에러코드가 511으로 바뀐것을 볼 수 있다.
방금은 파이썬 Exception을 상속받았다면, 이번에는 FastAPI의 HTTPException을 상속받아 에러를 정의해보자. 이 방법은 exception handler를 사용할 필요가 없다.
from typing import Any, Optional, Dict
from fastapi import FastAPI, HTTPException
class SomeFastAPIError(HTTPException):
def __init__(
self,
status_code: int,
detail: Any = None,
headers: Optional[Dict[str, Any]] = None,
) -> None:
super().__init__(
status_code=status_code, detail=detail, headers=headers
)
app = FastAPI()
@app.get("/error")
async def get_error():
raise SomeFastAPIError(511, "Hello")