本次的程式碼與目錄結構可以參考 FastAPI Tutorial : Day03 branch
在昨天把基本 FastAPI 的環境安裝好
今天要來做一些基本的設定,並且把 FastAPI 包裝成一個可以直接執行的檔案
將以下 code 貼到 main.py
中
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def hello_world():
return "Hello World"
@app.get("/users/{user_id}")
def get_users(user_id: int, qry: str = None):
return {"user_id": user_id, "query": qry }
接者可以在 terminal 中執行以下指令
來啟動 FastAPI 並且開在 5002 port 當有改動到時會 hot reload
uvicorn main:app --reload --host 0.0.0.0 --port 5002
應該會看到以下的結果
接著打開瀏覽器,輸入 http://localhost:5002
可以看到 Swagger UI 的介面
我們會在明天再細講 FastAPI 的架構
現在我們可以透過 uvicorn main:app --reload --host 0.0.0.0 --port 5002
但每次都要打這麼長的指令,有點麻煩
所以我們可以把 uviorn
包裝成 .py
再加上 .env
方便設定環境變數
其實主要是為了之後 database connect url 設定 !
包裝完成後的目錄結構如下:
.
├── main.py
├── run.py
└── setting
├── .env.dev
├── .env.prod
├── .env.test
└── config.py
可以參考 FastAPI Tutorial : Day03 的 branch
建立 /setting
目錄
各個 mode 的 .env
設定檔案
以及 config.py
作為需要環境變數的 dependency
mkdir setting
touch setting/.env.{dev,prod,test}
touch setting/config.py
.env
檔案內容如下:
.env.dev
APP_MODE='dev'
PORT=8001
RELOAD=True
DATABASE_URL='dev_database'
.env.test
APP_MODE='test'
PORT=8002
RELOAD=False
DATABASE_URL='test_database'
.env.prod
APP_MODE='prod'
PORT=8003
RELOAD=False
DATABASE_URL='prod_database'
引入 config.py
需要的套件
import os
from functools import lru_cache
from dotenv import load_dotenv
@lru_cache()
def get_settings():
load_dotenv( f".env.{os.getenv('APP_MODE')}")
return Settings()
建立 Settings
物件
class Settings():
app_name:str = "iThome2023 FastAPI Tutorial"
author:str = "Jason Liu"
app_mode: str = os.getenv("APP_MODE")
port:int = int(os.getenv("PORT"))
reload:bool = bool(os.getenv("RELOAD"))
database_url:str = os.getenv("DATABASE_URL")
因為等一下會在 run.py
中設定 APP_MODE
環境變數
所以我們可以透過 os.getenv('APP_MODE')
載入相對應的 .env
檔
@lru_cache()
def get_settings():
load_dotenv( f".env.{os.getenv('APP_MODE')}")
return Settings()
不過會遇到一個問題,就是每次需要環境變數時都需要跑一次 load_dotenv()
和 os.getenv()
所以我們可以透過 @lru_cache()
來做一個簡單的 cache
只有在第一次跑到 get_settings()
時才會去載入 .env
檔案,接下來都會從 cache 回傳 Setting()
的 instance
可以參考一下圖片
( 截自 FastAPI Advanced setting : creating the settings only once with lru_cache )
建立 run.py
touch run.py
在 run.py
中加入以下的 code
先引入會用到的套件
import argparse
import os
from dotenv import load_dotenv
import uvicorn
argparse
: 用來解析 command line 的參數os
和 dotenv
: 用來取得 .env
檔的環境變數uvicorn
: 這次包裝成 .py
之後就可以直接使用 run.py
來啟動 FastAPI 而不用以 uvicorn main:app --reload --host <host> --port <port>
來啟動接著我們要來解析 command line 的參數
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Run the server in different modes.")
parser.add_argument("--prod",action="store_true", help="Run the server in production mode.")
parser.add_argument("--test",action="store_true", help="Run the server in test mode.")
parser.add_argument("--dev",action="store_true", help="Run the server in development mode.")
args = parser.parse_args()
現在就能夠以 python run.py --dev
讓 FastAPI 以 development mode 啟動
以 python run.py --prod
讓 FastAPI 以 production mode 啟動
接著我們要來取得分別取得 .env
檔案中的環境變數
可以透過 load_dotenv()
來載入 setting/.env.*
檔案中的環境變數
並利用 os.getenv()
來取得環境變數
if args.prod:
load_dotenv("setting/.env.prod")
elif args.test:
load_dotenv("setting/.env.test")
else:
load_dotenv("setting/.env.dev")
uvicorn.run("main:app", host="0.0.0.0" , port=int(os.getenv("PORT")) , reload=bool(os.getenv("RELOAD")) )
最後我們要來修改 main.py
先從 setting/config.py
中引入 get_settings()
from setting.config import get_settings
加上 /infor
的測試 API 回傳目前載入的 setting
@app.get("/infor")
def get_infor():
settings = get_settings()
return {
"app_name": settings.app_name,
"author": settings.author,
"app_mode": settings.app_mode,
"port": settings.port,
"reload": settings.reload,
"database_url": settings.database_url
}
現在我們可以分透過 --<mode>
讓 FastAPI 載入不同設定檔
--dev
python run.py --dev
執行結果
以 curl
測試 /infor
API
curl http://localhost:8001/infor
curl
的結果
{"app_name":"iThome2023 FastAPI Tutorial","author":"Jason Liu","app_mode":"dev","port":8001,"database_url":"dev_database","reload":"True"}
--prod
python run.py --prod
執行結果
以 curl
測試 /infor
API
curl http://localhost:8003/infor
curl
的結果
{"app_name":"iThome2023 FastAPI Tutorial","author":"Jason Liu","app_mode":"prod","port":8003,"database_url":"prod_database","reload":"False"}
FastAPI : Advanced setting
FastAPI : Creating the settings only once with lru_cache
Python argparse
python-dotenv
lru_cache