FastAPI 實戰秘籍:從零構建高性能 API -配置篇
有關注朋友讓我講解一下fastapi進行web開發的教程,從今天分幾期講講一下fastapi項目的搭建。
官方文檔:https://fastapi.tiangolo.com/zh/
每個項目大多會有獨立于代碼外的配置文件,比如傳統軟件.ini配置,web開發的yaml或toml配置等。配置文件獨立能夠避免硬編碼,避免每次修改都要重啟服務。更好的團隊協作,敏感信息泄露等。
具體學習可查看代碼地址入選: https://github.com/pyzxs/zadmin。
我們使用pydantic_settings及PyYAML庫作為配置管理:
pip install pydantic-settings pyyaml
配置文件
在config目錄下存在config.dev.yml, 把git中的config.dev.yml拷貝為config.yml。
下面是實現配置調用的代碼如下:
# config/config.py
import os
from typing import Dict, Any, Optional
from typing import List
import yaml
from pydantic import BaseModel
from pydantic_settings import BaseSettings
# 根目錄地址
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
模型定義:
# config/config.py
# 子模型定義
class AppConfig(BaseModel):
name: str
version: str = "1.0"
host: str = "0.0.0.0"
port: int = 8000
debug: bool = False
secret_key: str
allowed_origins: List[str] = []
class DatabaseConfig(BaseModel):
url: str
async_url: str
pool_size: int = 10
echo_sql: bool = False
class RedisConfig(BaseModel):
host: str = "localhost"
port: int = 6379
password: str = ""
db: int = 0
class LoggingConfig(BaseModel):
level: str = "INFO"
log_path: str = "logs/app.log"
rotation: str = "10 MB"
# 主配置模型
class Settings(BaseSettings):
app: AppConfig
database: DatabaseConfig
redis: RedisConfig
logging: LoggingConfig
配置文件加載及初始數據類:
#config/config.py
# 全局緩存
_cached_config: Optional[Dict[str, Any]] = None
_cached_mtime: Optional[float] = None
def load_yaml_config_with_cache(file_path: str) -> Dict[str, Any]:
global _cached_config, _cached_mtime
current_mtime = os.path.getmtime(file_path)
if _cached_config isNoneor current_mtime != _cached_mtime:
print("讀取配置文件")
with open(file_path, "r", encoding="UTF-8") as f:
_cached_config = yaml.safe_load(f)
_cached_mtime = current_mtime
return _cached_config
def get_settings() -> Settings:
file_path = os.path.join(BASE_DIR, "config/config.yml")
config_data = load_yaml_config_with_cache(file_path)
return Settings(**config_data)
在上面代碼中增加全局緩存,避免每次調用get_settings都進行io操作。
而且緩存在內存中, 每個服務重啟都會自動清理掉。
測試配置文件效果:
# 測試
if __name__ == "__main__":
print(BASE_DIR)
settings1 = get_settings() # 第一次加載
settings2 = get_settings() # 從緩存讀取
print(settings1 == settings2) # True
# 運行測試 python config.py
讀取配置文件
True
入口文件及啟動
在根目錄下的main.py我們通過uvicorn作為 ASGI 服務器:
pip install fastapi uvicorn[standard]
代碼如下:
# main.py
import uvicorn
from fastapi import FastAPI
import config
# 獲取配置文件
settings = config.get_settings()
# 創建關于fastapi的app
def create_app():
"""啟動項目"""
app = FastAPI(
title=settings.app.name,
version=settings.app.version,
)
return app
if __name__ == '__main__':
if settings.app.debug:
uvicorn.run(app='main:create_app', host=settings.app.host, port=settings.app.port, reload=True, factory=True)
else:
uvicorn.run(app='main:create_app', host=settings.app.host, port=settings.app.port, factory=True)
啟動服務:
# 可直接運行
python main.py
# 通過uvicorn
uvicorn main:create_app --factory
可以通過http://localhost:8000/docs查看api文檔。