챗봇 구현 실습 (2) - FastAPI
fastapi는 python 3.6+ 의 api를 빌드하기위한 웹 프레임워크
= 백엔드에서 restful api를 간결하게 구현할 수 있는 프레임워크
api란?
우리가 해당 서비스의 구동 원리를 몰라도 해당 서비스를 사용하게 해주는 인터페이스.
실습
환경 설정
pip install fastapi
#for production, Uvicorn or Hypercorn과 같은 ASGI 서버기 필요
pip install "uvicorn[standard]"
예제 코드
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
원래는 def 해서 함수를 만들면 해당 함수의 기능만 하지만 @app.get(”/”)을 위에 붙임으로써(어노테이션) FastAPI()에 정의된 다른 함수 및 기능까지 사용하게됨.
@app.get("/")
def read_root():
return {"Hello": "World"}
이 코드의 의미는 해당 홈페이지의 루트(/)로 접근하면 {"Hello": "World"} 를 return 하라는 의미이다.
웹에는 CRUD라는 개념이 있다. 각각 Create, Read, Update, Delete이다.
app.get : Read
app.post : Create
app.put : Update
app.delete : Delete
프로그램 실행
uvicorn main:app --reload
여기서 main은 .py 파일명이고 app은 FastAPI() 클래스의 객체를 의미한다. —reload 옵션을 주면 코드의 변경을 저장할때 자동으로 서버에 반영해준다. 코드짜고 ctrl + s 하면 자동으로 연동이 된다.
path parameter
#Path parameter
@app.get("/items/{item_id}/{key}")
def read_item(item_id: int):#: int부분은 타입핑으로 fast api에 자료형에 대한 힌트를 준다. typing은 python에서 지원하는 기능.
item = items[item_id]
return item
#query parameter
@app.get("/items/{item_id}/{key}")
def read_item_and_key(item_id: int,key:str):#: int부분은 타입핑으로 fast api에 자료형에 대한 힌트를 준다. typing은 python에서 지원하는 기능.
item = items[item_id][key]
return item
query parameter
#query parameter
@app.get("/item-by-name")
def read_item_by_name(name:str):
for item_id, item in items.items():
if item['name'] == name:
return item
return {"error":"data not found"}
127.0.0.1:8000/item-by-name에서 검색을 사용할 수 있다. 검색을 할때 연산자는 ?이고 ? 뒤에 검색할 변수명= 변수에 저장된 값 을 하면 된다.
127.0.0.1:8000/item-by-name?name=bread
post
여기서는 from pydantic import BaseModel 을 추가해야한다. pydantic은 타입을 지정하는걸 도와주는 라이브러리. 데이터를 전달할때 규약을 정해준다고 함.
class Item(BaseModel):
name: str
price: int
위의 코드를 추가해서 외부에서 post 메서드로 서버에 요청이 온다면 Item의 형식에 맞는 입력이 있을때 입력대로 parsing을 해서 정보를 가져온다.
@app.post("/items/{item_id}") #이 경로로 create item을 하길 원한다.
def create_item(item_id: int, item: Item):
if item_id in items:
return {"error":"there is already existing key."}
items[item_id] = item.dict()
return {"success": "ok"}
put
create에 해당하는 작업
class ItemForUpdate(BaseModel):
name: Optional[str]
price: Optional[int]
Item을 update 할때 name or price가 없는 경우 오류가 발생. 이를 처리하기 위해 optional을 줘서 하나가 없어도 오류 안나게 한다.
@app.put("/items/{item_id}")
def update_item(item_id:int, item:ItemForUpdate):
if item_id not in items:
return {"error":f"there is no item id {item_id}"}
if item.name:
items[item_id]['name'] = item.name
if item.price:
items[item_id]['price'] = item.price
return {"success": "ok"}
delete
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
items.pop(item_id)
return {"success": "ok"}