AI测试平台学习第一天
`app/database.py` | SQLAlchemy引擎创建、Session管理、依赖注入`get_db()` |环境变量管理:`.env`文件 → `pydantic-settings` → `settings`单例。| `app/config.py` | Pydantic Settings配置管理,环境变量加载 || `app/main.py:1-32` | FastAPI应用初始化、
第一阶段:项目基础架构
| 文件 | 学习重点 |
|------|----------|
| `run.py` | Uvicorn启动入口,理解ASGI服务器 |
| `app/config.py` | Pydantic Settings配置管理,环境变量加载 |
| `app/database.py` | SQLAlchemy引擎创建、Session管理、依赖注入`get_db()` |
| `app/main.py:1-32` | FastAPI应用初始化、CORS中间件、路由注册 |
**核心知识点**:
- FastAPI生命周期:启动时`Base.metadata.create_all()`自动建表
- 依赖注入模式:`db: Session = Dep
环境变量管理:`.env`文件 → `pydantic-settings` → `settings`单例
1. run.py - 启动入口(9行)
逐行解析:
第1行:import uvicorn
uvicorn是一个ASGI服务器(异步服务器网关接口)- 类比:如果FastAPI是"餐厅厨房",uvicorn就是"服务员",负责接收HTTP请求并转交给厨房处理
- 安装来源:
requirements.txt中的uvicorn==0.24.0
第3行:if __name__ == "__main__":
- Python的标准写法,确保这段代码只在直接运行时执行,被import时不执行
__name__是Python内置变量:- 直接运行
python run.py→__name__等于"__main__" - 被其他文件
import run→__name__等于"run"
- 直接运行
第4-8行:uvicorn.run(...)
"app.main:app"→ 这是模块路径:变量名的格式app.main= 找到app/main.py文件:app= 找到该文件中的app变量(即FastAPI实例)
host="0.0.0.0"→ 监听所有网络接口(局域网其他设备也能访问)- 如果写
127.0.0.1则只能本机访问
- 如果写
port=8000→ 端口号8000reload=True→ 开发模式,代码修改后自动重启服务器- 生产环境应设为False(性能更好)
问题:为什么单独一个run.py?
- 解耦:启动配置和应用逻辑分离
- 灵活:可以有多个启动文件(如
run_prod.py用不同配置) - 规范:这是FastAPI项目的标准做法
2. app/config.py - 配置管理(39行)
逐行解析:
第1行:from pathlib import Path
pathlib是Python 3.4+的路径处理库,比os.path更优雅- 用于构建文件路径(跨平台兼容Windows/Mac/Linux)
第2行:from pydantic_settings import BaseSettings
pydantic-settings是Pydantic的扩展,专门用于配置管理- 安装来源:
pydantic-settings==2.1.0 - 核心功能:自动从环境变量或**.env文件**读取配置
第4行:BASE_DIR = Path(__file__).resolve().parent.parent
__file__= 当前文件路径,如C:\Users\admin\Desktop\小程序\测试平台\app\config.py.resolve()= 转为绝对路径.parent= 上一级目录(第一次)→app/.parent= 上一级目录(第二次)→测试平台/- 结果:
BASE_DIR指向项目根目录
第7行:class Settings(BaseSettings):
- 继承
BaseSettings,获得自动读取环境变量的能力 - 所有属性都会自动尝试从环境变量加载
第9-13行:数据库配置(带默认值)
DB_HOST: str = "localhost"→ 类型标注 + 默认值- 如果环境变量中没有
DB_HOST,则使用默认值"localhost" - 注意:第12行的密码是硬编码的默认值,生产环境应通过.env覆盖
第16-18行:MIMO API配置
MIMO_API_KEY和MIMO_BASE_URL默认为空字符串- 必须在
.env中配置才能使用AI功能 MIMO_MODEL有默认值"mimo-v2.5-pro"
第30-32行:@property database_url
@property装饰器:把方法变成属性访问- 使用时写
settings.database_url(不需要加括号) - 拼接MySQL连接字符串格式:
mysql+pymysql://用户名:密码@主机:端口/数据库名?charset=utf8mb4 pymysql是Python的MySQL驱动
第34-36行:class Config(嵌套类)
- 这是
pydantic-settings的特殊约定 env_file= 指定从哪个.env文件读取配置env_file_encoding= 文件编码- Pydantic会自动解析
.env文件中的键值对
第39行:settings = Settings()
- 实例化 Settings 对象
- 此时会立即读取
.env文件和环境变量 - 整个应用中通过
from app.config import settings引用这个单例
配置加载优先级(从高到低):
- 系统环境变量
.env文件- 代码中的默认值
3. app/database.py - 数据库配置(25行)
逐行解析:
第1-3行:SQLAlchemy三大核心导入
create_engine→ 创建数据库引擎(连接池管理器)declarative_base→ 创建模型基类(所有表模型都继承它)sessionmaker→ 创建会话工厂(生成数据库操作的session)
第7-13行:创建引擎
settings.database_url→ 从config获取连接字符串echo=True→ 打印SQL语句(开发调试用,生产应关掉)pool_pre_ping=True→ 使用前先ping一下连接,防止用到已断开的连接pool_size=10→ 连接池保持10个空闲连接max_overflow=20→ 最多溢出20个额外连接(高峰期用)- 总共最多 10+20=30 个并发连接
类比:连接池就像"共享单车停放点":
pool_size= 停放点常备的车max_overflow= 高峰期临时多放的车pool_pre_ping= 骑之前先检查车有没有坏
第15行:SessionLocal = sessionmaker(...)
- 创建会话工厂(注意不是会话本身)
autocommit=False→ 不自动提交事务(需要手动commit)autoflush=False→ 不自动刷新到数据库bind=engine→ 绑定到上面创建的引擎
第17行:Base = declarative_base()
- 创建模型基类
- 所有表模型(如TestCase、User)都继承这个类
- SQLAlchemy通过它来管理表结构映射
第20-25行:get_db() 依赖注入函数
- 这是一个生成器函数(使用
yield) db = SessionLocal()→ 从工厂创建一个会话yield db→ 把会话交给FastAPI的路由函数使用finally: db.close()→ 无论是否出错,都关闭会话- 这是FastAPI的依赖注入模式
为什么用yield而不是return?
yield是生成器,FastAPI会在请求处理完后自动执行yield后面的代码- 这样保证了
db.close()一定会执行(类似try-finally的效果)
4. app/main.py - FastAPI应用入口(前32行)
逐行解析:
第1行:from fastapi import FastAPI
- FastAPI框架的核心类,创建应用实例
第2行:from fastapi.middleware.cors import CORSMiddleware
- CORS中间件(跨域资源共享)
- 解决前后端分离时的跨域问题
- 比如前端在
localhost:3000,后端在localhost:8000,浏览器会阻止请求
第3行:from fastapi.responses import HTMLResponse
- 用于返回HTML页面(后面首页路由用到)
第5-7行:导入配置和路由
settings→ 全局配置单例engine, Base→ 数据库引擎和模型基类testcase, ai, chat...→ 7个路由模块
第9行:Base.metadata.create_all(bind=engine) ⭐ 重要
- 自动建表:扫描所有继承Base的模型类,在数据库中创建对应的表
metadata= 存储所有表结构信息的容器create_all= 如果表不存在就创建,已存在则跳过- 这行代码在应用启动时执行一次
第11-15行:创建FastAPI实例
title→ API文档标题(Swagger UI中显示)version→ 版本号description→ API文档描述- 启动后访问 http://localhost:8000/docs 可看到自动生成的API文档
第17-23行:CORS中间件配置 ⭐ 重要
allow_origins=["*"]→ 允许所有域名访问allow_credentials=True→ 允许携带Cookieallow_methods=["*"]→ 允许所有HTTP方法(GET/POST/PUT/DELETE...)allow_headers=["*"]→ 允许所有请求头
为什么要CORS? 浏览器的同源策略禁止网页向不同源的服务器发请求:
- 前端:http://localhost:8000(HTML页面)
- 后端API:http://localhost:8000/api/...
- 虽然同端口,但浏览器仍可能限制,配置CORS是最安全的做法
第25-31行:注册路由
include_router→ 把每个模块的路由挂载到主应用- 类比:把各个部门的电话簿合并到总机
📁 补充:app/__init__.py
- 空文件,但必须存在
- Python的约定:有
__init__.py的目录才是包(package) - 没有它,
from app.config import settings会报错
📁 补充:.env.example 和 .env
.env 文件的作用:
- 存储敏感配置(密码、API密钥等)
- 不提交到Git(已在
.gitignore中排除) - 格式:
KEY=VALUE(每行一个)
配置加载流程:
.env文件 → pydantic-settings读取 → Settings实例 → settings对象
↑
系统环境变量(优先级更高)
🔄 请求处理全流程
现在你已经理解了基础架构,让我画一个完整的请求处理流程:
用户浏览器
│
▼
http://localhost:8000/api/testcases?user_id=1
│
▼
┌─────────────────────────────────────────┐
│ run.py │
│ uvicorn.run("app.main:app", ...) │
│ ↓ │
│ Uvicorn服务器接收HTTP请求 │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ app/main.py │
│ app = FastAPI(...) │
│ ↓ │
│ CORS中间件处理跨域 │
│ ↓ │
│ 路由匹配:/api/testcases → testcase.py │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ app/routers/testcase.py │
│ @router.get("") │
│ def get_testcases(user_id, db=Depends(get_db)): │
│ ↓ │
│ Depends(get_db) 触发 database.py │
│ → 创建数据库Session │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ app/services/testcase_service.py │
│ testcase_service.get_testcases(db, ...) │
│ ↓ │
│ SQLAlchemy查询 → MySQL数据库 │
│ ↓ │
│ 返回结果 │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 返回JSON响应 │
│ {"total": 10, "items": [...]} │
│ ↓ │
│ get_db() 的 finally 执行 │
│ → db.close() 关闭Session │
└─────────────────────────────────────────┘
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)