본문 바로가기
Python/API

Fast API Tutorial(3.5): toy project(calculator)

by 고독한석사생 2024. 3. 1.

Fast API의 기능을 간단히 익힌 상태에서, API와 python으로 간단히 웹을 만들 수 있는 streamlit을 이용해 간단한 계산기를 만들어 보자

전체 모듈 구성

api.py: Fast api 모듈
calculator.py: 계산기 모듈
streamlit_app.py: streamlit 모듈
 
main.py: Fast api와 streamlit을 실행하는 메인 모듈
 
우리는 streamlit을 통해 웹 화면에서 x, y 두 float 값과 operator(+, -, /, *)를 입력 -> 입력된 값이 api를 통해 결과를 반환 -> 반환된 결과가 다시 streamlit 웹 화면에 게시되도록 할 예정이다.
 

1. Fast API

이 부분에서는 API 통신을 통해 계산기 인자를 받아 결과를 뱉어내도록 만드는 것이 목표다.

1-1. API 모듈

from fastapi import FastAPI  # api 모듈
from pydantic import BaseModel  # api 값 검증 모듈

import calculator  # 사용자 계산기 모듈

app = FastAPI()


@app.get("/", description="main route")
async def get_root_route():
    return {"message":"hello world"}

class formula(BaseModel):
    """
    pydantic 모듈을 활용해 x, y, operator값 type 지정
    """
    x: float
    y: float
    operator: str

@app.post("/calculator", description='계산식을 사용자가 인풋으로 넣습니다.')
async def input_formula(Input:formula):
    """
    Input을 우리가 지정한 class를 받아 계산기 각 인자(x,y,operator) 할당
    여기서 type 검증된 값이 들어감
    return: 계산기 모듈의 리턴 결과
    """
    result = calculator.calculate_values(x=Input.x, y=Input.y, operator=Input.operator)
    return result

 
 

 

1-2. 계산기 모듈

def calculate_values(x, y, operator):
    """
    두 수에 대한 기본적인 사칙연산 수행
    : 곱하기, 나누기, 더하기, 빼기
    return: 두 수의 사칙연산 결과
    """
    if operator=='+':
        val = x+y
    elif operator=='-':
        val = x-y
    elif operator=='/':
        if y==0:
            val = 'y must not be zero'
        else:
            val = x/y
    elif operator=='*':
        val = x*y
    return val

 

2. Streamlit

import streamlit as st
import json
import requests


# 사용자가 웹에서 보이는 화면
# 두 수를 사용자는 입력하고 연산자를 선택
# 결과를 dictionary로 받아 fast api로 requerts모듈을 활용해 post -> fast api로부터 결과를 받아옴
# 웹 상에서 결과를 보여줌
st.title("This is my first API toy project")
st.subheader("Basic Caculator")

x = st.text_area('x 숫자 입력') # number_input하면, format 등 지정 번거로움 -> api에서 pydantic 검증을 통해 float로 인풋됨
operator = st.selectbox("부등호", ("+", "-", "/", "*"))
y = st.text_area('y 숫자 입력')

info_dict = {'x':x, 'y':y, 'operator':operator}

# it returns a True if the button was clicked on the last run of the app, and False otherwise.
if st.button('Calculate'):
    result = requests.post(url='http://{your fixed PC IP}:8000/calculator', data=json.dumps(info_dict), verify=False)
   
    st.subheader(f"result: {result.text}")

 
requerts.post에서 url 인자에 127.0.0.1을 하면 localhost 지정이고,
고정 IP 지정 시, 서버가 열렸을 때 동일한 네트워크 사용중이면 폰에서도 볼 수 있음
- 고정 ip 지정 후 {}는 제거
 

3. 최종

import threading
import subprocess

def run_streamlit():
    subprocess.run(['streamlit', 'run', 'streamlit_app.py'])

def run_fastapi():
    subprocess.run(['uvicorn', 'api:app', '--reload', '--host={your fixed PC IP}'])


if __name__=="__main__":
    # Streamlit을 실행하는 스레드 시작
    streamlit_thread = threading.Thread(target=run_streamlit)
    streamlit_thread.start()

    # FastAPI를 실행하는 스레드 시작
    fastapi_thread = threading.Thread(target=run_fastapi)
    fastapi_thread.start()

    # 두 스레드가 모두 종료될 때까지 대기
    streamlit_thread.join()
    fastapi_thread.join()

 
- 고정 ip 지정 후 {}는 제거(2번 위 설명과 동일)
 
fast api 서버와 streamlit 서버를 동시에 열어야 되므로, threading 모듈 활용해 동시 작업 수행

main.py 실행 후 명령 프롬프트 창

 
 

실행 화면 예시

 

결과 반환이 잘 되는 것을 확인

 

나눗셈 시, y가 0이 안되는 결과도 잘 반환됨

 
고정 IP로 진행하여 폰으로도 결과를 확인할 수 있었음

 
 
튜토리얼을 따라만 치다가 한 번 직접해보니까 동작 원리를 잘 이해할 수 있었다
데이터 과학 분야에서 분석 결과를 잘 활용할 때 이런 방법을 잘 응용하면 좋을 거 같다고 느낌

반응형

'Python > API' 카테고리의 다른 글

Fast API Tutorial(3): query parameters  (0) 2024.02.24
Fast API Tutorial(2): path parameters  (0) 2024.02.23
Fast API Tutorial(1): introduction  (0) 2024.02.23