Spaces:
Paused
Paused
| import os | |
| import time | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI | |
| from starlette.middleware.cors import CORSMiddleware | |
| from cleanup_scheduler import start_cleanup_scheduler, stop_cleanup_scheduler | |
| from config import ( | |
| logger, | |
| OUTPUT_DIR, | |
| DEEPFACE_AVAILABLE, | |
| DLIB_AVAILABLE, | |
| MODELS_PATH, | |
| IMAGES_DIR, | |
| YOLO_AVAILABLE, | |
| ENABLE_LOGGING, | |
| HUGGINGFACE_SYNC_ENABLED, | |
| ) | |
| from database import close_mysql_pool, init_mysql_pool | |
| from utils import ensure_bos_resources, ensure_huggingface_models | |
| logger.info("Starting to import api_routes module...") | |
| if HUGGINGFACE_SYNC_ENABLED: | |
| try: | |
| t_hf_start = time.perf_counter() | |
| if not ensure_huggingface_models(): | |
| raise RuntimeError("无法从 HuggingFace 同步模型,请检查配置与网络") | |
| hf_time = time.perf_counter() - t_hf_start | |
| logger.info("HuggingFace 模型同步完成,用时 %.3fs", hf_time) | |
| except Exception as exc: | |
| logger.error(f"HuggingFace model preparation failed: {exc}") | |
| raise | |
| else: | |
| logger.info("已关闭 HuggingFace 模型同步开关,跳过启动阶段的同步步骤") | |
| try: | |
| t_bos_start = time.perf_counter() | |
| if not ensure_bos_resources(): | |
| raise RuntimeError("无法从 BOS 同步模型与数据,请检查凭证与网络") | |
| bos_time = time.perf_counter() - t_bos_start | |
| logger.info(f"BOS resources synchronized successfully, time: {bos_time:.3f}s") | |
| except Exception as exc: | |
| logger.error(f"BOS resource preparation failed: {exc}") | |
| raise | |
| try: | |
| t_start = time.perf_counter() | |
| from api_routes import api_router, extract_chinese_celeb_dataset_sync | |
| import_time = time.perf_counter() - t_start | |
| logger.info(f"api_routes module imported successfully, time: {import_time:.3f}s") | |
| except Exception as e: | |
| import_time = time.perf_counter() - t_start | |
| logger.error(f"api_routes module import failed, time: {import_time:.3f}s, error: {e}") | |
| raise | |
| try: | |
| t_extract_start = time.perf_counter() | |
| extract_result = extract_chinese_celeb_dataset_sync() | |
| extract_time = time.perf_counter() - t_extract_start | |
| logger.info( | |
| "Chinese celeb dataset extracted successfully, time: %.3fs, target: %s", | |
| extract_time, | |
| extract_result.get("target_dir"), | |
| ) | |
| except Exception as exc: | |
| logger.error(f"Failed to extract Chinese celeb dataset automatically: {exc}") | |
| raise | |
| async def lifespan(app: FastAPI): | |
| start_time = time.perf_counter() | |
| logger.info("FaceScore service starting...") | |
| logger.info(f"Output directory: {OUTPUT_DIR}") | |
| logger.info(f"DeepFace available: {DEEPFACE_AVAILABLE}") | |
| logger.info(f"YOLO available: {YOLO_AVAILABLE}") | |
| logger.info(f"MediaPipe available: {DLIB_AVAILABLE}") | |
| logger.info(f"Archive directory: {IMAGES_DIR}") | |
| os.makedirs(OUTPUT_DIR, exist_ok=True) | |
| # 初始化数据库连接池 | |
| try: | |
| await init_mysql_pool() | |
| logger.info("MySQL 连接池初始化完成") | |
| except Exception as exc: | |
| logger.error(f"初始化 MySQL 连接池失败: {exc}") | |
| raise | |
| # 启动图片清理定时任务 | |
| logger.info("Starting image cleanup scheduled task...") | |
| try: | |
| start_cleanup_scheduler() | |
| logger.info("Image cleanup scheduled task started successfully") | |
| except Exception as e: | |
| logger.error(f"Failed to start image cleanup scheduled task: {e}") | |
| # 记录启动完成时间 | |
| total_startup_time = time.perf_counter() - start_time | |
| logger.info(f"FaceScore service startup completed, total time: {total_startup_time:.3f}s") | |
| yield | |
| # 应用关闭时停止定时任务 | |
| logger.info("Stopping image cleanup scheduled task...") | |
| try: | |
| stop_cleanup_scheduler() | |
| logger.info("Image cleanup scheduled task stopped") | |
| except Exception as e: | |
| logger.error(f"Failed to stop image cleanup scheduled task: {e}") | |
| # 关闭数据库连接池 | |
| try: | |
| await close_mysql_pool() | |
| except Exception as exc: | |
| logger.warning(f"关闭 MySQL 连接池失败: {exc}") | |
| # 创建 FastAPI 应用 | |
| app = FastAPI( | |
| title="Enhanced FaceScore 服务", | |
| description="支持多模型的人脸分析REST API服务,包含五官评分功能。支持混合模式:HowCuteAmI(颜值+性别)+ DeepFace(年龄+情绪)", | |
| version="3.0.0", | |
| docs_url="/cp_docs", | |
| redoc_url="/cp_redoc", | |
| lifespan=lifespan, | |
| ) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # 注册路由 | |
| app.include_router(api_router) | |
| # 添加根路径处理 | |
| async def root(): | |
| return "UP" | |
| if __name__ == "__main__": | |
| import uvicorn | |
| if not os.path.exists(MODELS_PATH): | |
| logger.critical( | |
| "Warning: 'models' directory not found. Please ensure it exists and contains model files." | |
| ) | |
| logger.critical( | |
| "Exiting application as FaceAnalyzer cannot be initialized without models." | |
| ) | |
| exit(1) | |
| # 根据日志开关配置 Uvicorn 日志 | |
| if ENABLE_LOGGING: | |
| uvicorn.run(app, host="0.0.0.0", port=8080, reload=False) | |
| else: | |
| # 禁用 Uvicorn 的访问日志和错误日志 | |
| uvicorn.run( | |
| app, | |
| host="0.0.0.0", | |
| port=8080, | |
| reload=False, | |
| access_log=False, # 禁用访问日志 | |
| log_level="critical" # 只显示严重错误 | |
| ) | |