python restful API服务器fastAPI
组件
-
fastAPI : https://fastapi.tiangolo.com/
-
uvicorn: https://www.uvicorn.org/
快速开始
# 安装fastAPI
pip install fastapi -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装web容器
pip install "uvicorn[standard]" -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装from参数表单
pip install python-multipart -i https://pypi.tuna.tsinghua.edu.cn/simple
编写代码
# main.py
from fastapi import FastAPI, APIRouter
from fastapi.staticfiles import StaticFiles
app = FastAPI()
router = APIRouter()
# 静态目录
app.mount("/static", StaticFiles(directory="./static"), name="static")
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/")
async def read_root():
html_content = """
<html>
<head>
<title>FastAPI</title>
</head>
<body>
<h1>Hello, FastAPI!</h1>
<p>
<a href="https://fastapi.tiangolo.com">
https://fastapi.tiangolo.com
</a>
</p>
</body>
</html>
"""
return HTMLResponse(content=html_content, media_type="text/html")
# 运行
uvicorn main:app --reload
# 也可以用代码实现
if __name__ == "__main__":
uvicorn.run(app, host="localhost", port=8000)
# 生成环境运行参数
# uvicorn main:app --reload --host=localhost --port=8000
约定和规范
- 项目结构
├── main.py # 主应用文件
├── config.py # 配置文件
├── run.py # 启动脚本
├── requirements.txt # 项目依赖
├── .env # 环境变量
├── README.md # 项目说明
├── routers/ # 路由
├── models/ # 数据模型
├── schemas/ # 数据架构
├── repositories/ # 数据库操作
├── services/ # 业务逻辑
└── utils/ # 工具类
公共日志类
# common_logger.py
import logging
import sys
__all__ = ["get_logger"]
# 1. 只初始化一次
_INITIALIZED = False
# 2. 颜色表 + Windows 兼容
COLORS = {
"DEBUG": "\033[36m",
"INFO": "\033[32m",
"WARNING": "\033[33m",
"ERROR": "\033[31m",
"CRITICAL": "\033[35m",
"RESET": "\033[0m",
}
def _init_logger(level: int = logging.INFO):
global _INITIALIZED
# force=True 防止重复
if _INITIALIZED:
return
class ColorFormatter(logging.Formatter):
def format(self, record):
levelname = record.levelname
record.levelname = (
f"{COLORS.get(levelname, '')}{levelname}{COLORS['RESET']}"
)
return super().format(record)
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(
ColorFormatter(
fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
)
logging.basicConfig(level=level, handlers=[handler], force=True)
# force=True 防止重复
_INITIALIZED = True
def get_logger(name: str, level: int = logging.INFO) -> logging.Logger:
_init_logger(level)
return logging.getLogger(name)
uvicorn 日志根式统一
#!/usr/bin/env python3
"""
FastAPI 应用启动脚本
"""
import uvicorn
from config import settings
from common_logger import get_logger
log = get_logger(__name__)
LOGGING_CONFIG = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"default": {
"fmt": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
},
"access": {
"fmt": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
},
},
}
if __name__ == "__main__":
log.info(f"启动 {settings.app_name} v{settings.app_version}")
log.info(f"服务器地址: http://{settings.host}:{settings.port}")
# print(f"API 文档: http://{settings.host}:{settings.port}/docs")
log.info("-" * 50)
uvicorn.run(
"main:app",
host=settings.host,
port=settings.port,
reload=settings.reload,
log_level=settings.log_level.lower(),
log_config=LOGGING_CONFIG,
)