FastAPI -3

-·2022년 1월 14일
0

강의정리 - MLOps

목록 보기
11/18

이 글은 부스트캠프 ai tech 변성윤 강사님의 model serving 강의를 정리한 글입니다. :)
문제가 있거나, 틀린점이 있다면 말씀해주세요 !

JODONG2

목차

  • FastAPI 익숙해지기
    -- Event Handler
    -- API Router
    -- Error Handling
    -- Background Task

  • FastAPI가 어렵다면
    -- 프로젝트 구조 - Cookiecutter
    -- 객체지향
    -- Try&Error

Fast API 익숙해지기

Event Handler

  • 이벤트가 발생했을 때, 그 처리를 담당하는 함수
    -- Event Handler 정리
  • FastAPI에선 Application이 실행할 때, 종료될 때 특정 함수를 실행할 수 있음

app = FastAPI()

items= {} 

@app.on_event("startup") 
def startup_event(): 
    print("Startup event") 
    items["start"] = {"name":"ㅠ^ㅠ"}
    items["event"] = {"name":"^-^"}

@app.on_event("shutdown") 
def shutdown_event(): 
    print("Shutdown event") 
    with open("log.txt", mode= 'a') as log : 
        log.write("application shutdown") 

@app.get('/items/{item_id}')
def read_item(item_id: str): 
    return items[item_id]
- @app.on_event("startup") - @app.on_event("shutdown")
  • 예시
    -- startup 할 때 ML 모델 Load
    -- 시작되는 시간, 종료되는 시간,
    -- batch point
이거때문에 stylegan 프로젝트에서 애먹었었는데 TF는 어떻게 하나요,, TF 세션(?)에 넣어야 되던디..어렵다 ;-;

-- shutdown 할 때 로그 저장

API Router

  • API Router는 더 큰 애플리케이션들에서 많이 사용되는 기능

  • API Endpoint를 정의

  • Python Subpackage

  • APIRouter는 Mini FastAPI로 여러 API를 연결해서 활용

  • 기존에 사용하던 @app.get, @app.post을 사용하지 않고, router 파일을 따로 설정하고 app에 include해서 사용

from fastapi import FastAPI, APIRouter

user_router = APIRouter(prefix='/users')
order_router = APIRouter(prefix="/orders") 

@user_router.get("/", tags=["users"]) 
...
...
app = FastAPI()
app.include_router(user_router)
app.include_router(order_router) 

include_router를 name == main 안에서 실행할경우 uvicorn.run("module:app", ~~)을 실행하면 app에 다른 라우터들이 포함안되어있다. app=FastAPI() 선언해준 지역에서 같이 include_router를 실행하니 해결됨 !! 
"Module:app" Module: py 파일 이름, app : FastAPI()객체 이름
reload = True,
worker = n 사용하려니 위와 같이 "Module:app"으로 선언해야된다...

예제 프로젝트 구조

위에 예제에서는 main안에 order있고 user있고.. 

Error Handling

  • Error Handling은 웹서버를 안정적으로 운영하기 위해 반드시 필요한 주제
  • 서버에서 Error가 발생한 경우, 어떤 Error가 발생했는지 알아야 하고 요청한 클라이언트에 해당 정보를전달해 대응할 수 있어야 함
  • 서버 개발자는 모니터링 도구를 사용해 Error Log를 수집해야 함
  • 발생하고 있는 오류를 빠르게 수정할 수 있도록 예외처리를 잘 만들 필요가 있음
from fastapi import FastAPI
import uvicorn

app = FastAPI()
items= {
	1: "JODONG2",
    2: "DoNgineer",
    3: "^-^"
    }

@app.get("/v1/{item_id}")
async def find_by_id(item_id: int):
	return items[item_id]

if __name__ == "__main__":
	uvicorn.run(app, host="0.0.0.0", port=8000) 
  • 간단한 코드지만 Error를 발생할 확률이 높음
  • item_id가 1~3까진 정상
  • 4 이상의 숫자가 들어올 경우 Key Error가 발생
  • Internal Server Error

item_id가 1일 경우 정상적으로 200 return
item_id가 5일 경우 Internal server Error 500 return

  • 이렇게 되면 클라이언트는 어떤 에러가 난 것인지 정보를 얻을 수 없고, 자세한 에러를 보려면 서버에 직접 접근해서 로그를 확인해야 함

  • 에러 핸들링을 더 잘하려면 에러 메시지와 에러의 이유 등을 클라이언트에 전달하도록 코드를 작성해야 함

  • 터미널에서도 Error가 발생하고 있는 것을 확인할 수 있음

  • FastAPI의 HTTPException은 Error Response를 더 쉽게 보낼 수 있도록 하는 Class
    -- from fastapi import HTTPException

  • HTTPException을 이용해서 클라이언트에게 더 자세한 에러 메시지를 보내는 코드 작성

함수가 실패할것 같다고 느껴지면 예외처리를 해주는게 좋음. 
이 흐름에서 이상할 수 있겠는데...? -> raise 조지기

Background Task

  • FastAPI는 Starlett이라는 비동기 프레임워크를 래핑해서 사용

  • FastAPI의 기능 중 Background Tasks 기능은 오래 걸리는 작업들을 background에서 실행함

  • Online Serving에서 CPU 사용이 많은 작업들을 Background Task로 사용하면,
    -- 클라이언트는 작업 완료를 기다리지 않고 즉시 Response를 받아볼 수 있음

  • 특정 작업 후, 이메일 전송하는 Task 등

  • Background Tasks를 사용하지 않은 작업들은 작업 시간만큼 응답을 기다림

Github 참조 
run_tasks_in_fastapi : 서버를 띄우는 역할
app_2 = FastAPI()

@app_2.post("/task",status_code=202) 
async def create_task_in_background(task_input: TaskInput, background_tasks: BackgroundTasks):
	background_tasks.add_task(cpu_bound_task,task_input.wait_time) 
    return "ok"
start_time = datetime.now()
run_tasks_in_fastapi(app_2,tasks)
end_time = datetime.now()
print(start_time, end_time) 
  • 작업 결과물을 조회할 때는 Task를 어딘가에 저장해두고, GET요청을 통해 Task가 완료됐는지 확인

FastAPI가 어렵다면

orm, 인증,.., 등 다양한게 있는데 봐줬다... - 강사님 
감사함미다... - 감자 
  • 처음 백엔드 프로그래밍을 할 때 어려웠음 - 왜 어려울까?

  • 프로젝트 구조를 어떻게 잡아야 할지 모르겠다
    -- 코드를 main.py train.py predict.py 구조를 잘 안잡고 코딩하는게 익숙해짐.

  • 객체 지향이 낯설다
    -- 주피터노트북으로 학습하다보니 절차지향으로 알고 있는게 대부분...

  • 백엔드 프로그래밍 자체가 처음
    -- 알아야되는 기본 지식 없이 시도했다..

  • 목표의 부재

프로젝트 구조 - Cookiecutter

  • 쿠키를 만들 때 사용하는 Cookiecutter (=라이브러리)

  • 많은 사람들이 프로젝트 구조에 대한 고민이 많아 템플릿을 서로 공유

  • CLI형태로 프로젝트 생성 과정을 도와줌

  • 회사에서 공통의 프로젝트 구조가 필요하면 쿠키 커터로 설정

  • 개인용 쿠키 커터 템플릿을 만드는 것도 좋은 방법

  • 파일도 저장할 수 있음.

  • 도커 이미지처럼 구조를 찍어낼 수 있음.

  • Cookiecutter Data Science (=리서치 성 쿠키 ㅎㅎ)

  • cookiecutter-fastapi

  • 아예 처음 진행할 때는 일단 하나의 파일에 모두 코드 작성해서 FastAPI에 익숙해지고

  • 그 이후에 다른 프로젝트 구조를 참고해서 코드 개선

  • 클린 아키텍처 류의 책을 보면서 계속 구조 고민해보기

객체지향

  • 절차형 프로그래밍 vs 객체지향 프로그래밍의 차이 이해해보기

  • 객체지향프로그래밍은 코드의 중복을 최소화해서 재사용성을 증가시킴
    -- 주피터노트북은 사실 위에서부터 쭉 실행함..

  • 복잡한 로직이 들어갈수록 점점 빛을 발휘함

  • 현재 가지고 있는 코드를 Class로 변경해보기

  • Pydantic Use Case 탐색하기

Try&Error

  • 백엔드 프로그래밍이 처음이면 낯선 것이 당연
  • 코드를 작성하고 => 실행하고 => 수정하는 Flow
  • 조급해하지 않고 작은 규모의 프로젝트부터 하나씩 만들기
  • 목표를 설정하고(무엇을 만들겠다) => 기능을 정의 => 하나씩 구현
  • 막연히 FastAPI를 학습해야지보다는 프로젝트를 FastAPI백엔드로 구현! 등으로 목표 설정
  • 그 다음 강의는 Code Level에서 어떻게 진행하는지 IDE를 보며 강의할 예정

다음 강에서 가르쳐주는 도커를 학습하고 나선 어떻게 연결할까? 이런식으로 생각해보기

뭔가를 만들고 있다는 생각을 해보자 !!

취향 저격 멘트... 

프론트와 백엔드를 분리하는데 백엔드를 fastAPI로 하나씩 구현해보자 !

profile
-

0개의 댓글