""" FastAPI应用主入口 """ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from api.routes import config, trades, stats, dashboard, account, recommendations import os import logging from pathlib import Path from logging.handlers import RotatingFileHandler # 加载.env文件 try: from dotenv import load_dotenv backend_dir = Path(__file__).parent.parent project_root = backend_dir.parent env_file = backend_dir / '.env' if not env_file.exists(): env_file = project_root / '.env' if env_file.exists(): load_dotenv(env_file) else: load_dotenv(project_root / '.env', override=False) except ImportError: pass except Exception: pass # 配置日志 def setup_logging(): """配置日志系统""" # 获取日志级别 log_level = os.getenv('LOG_LEVEL', 'INFO').upper() log_level_map = { 'DEBUG': logging.DEBUG, 'INFO': logging.INFO, 'WARNING': logging.WARNING, 'ERROR': logging.ERROR, 'CRITICAL': logging.CRITICAL } level = log_level_map.get(log_level, logging.INFO) # 创建日志目录 backend_dir = Path(__file__).parent.parent log_dir = backend_dir / 'logs' log_dir.mkdir(exist_ok=True) # 日志文件路径 log_file = log_dir / 'api.log' # 配置根日志记录器 root_logger = logging.getLogger() root_logger.setLevel(level) # 清除现有的处理器 root_logger.handlers.clear() # 创建格式器 formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 文件处理器(带轮转) file_handler = RotatingFileHandler( log_file, maxBytes=10 * 1024 * 1024, # 10MB backupCount=5, encoding='utf-8' ) file_handler.setLevel(level) file_handler.setFormatter(formatter) root_logger.addHandler(file_handler) # 控制台处理器 console_handler = logging.StreamHandler() console_handler.setLevel(level) console_handler.setFormatter(formatter) root_logger.addHandler(console_handler) # 设置第三方库的日志级别 logging.getLogger('uvicorn').setLevel(logging.WARNING) logging.getLogger('uvicorn.access').setLevel(logging.WARNING) return log_file # 初始化日志 log_file = setup_logging() logger = logging.getLogger(__name__) logger.info(f"日志系统已初始化,日志文件: {log_file}") logger.info(f"日志级别: {os.getenv('LOG_LEVEL', 'INFO')}") # 检查 aioredis 是否可用 try: import aioredis logger.info(f"✓ aioredis 已安装 (版本: {aioredis.__version__ if hasattr(aioredis, '__version__') else '未知'})") except ImportError as e: import sys logger.warning("⚠ aioredis 未安装,Redis/Valkey 缓存将不可用") logger.warning(f" Python 路径: {sys.executable}") logger.warning(f" 导入错误: {e}") logger.warning(f" 提示: 请运行 'pip install aioredis==2.0.1' 安装 aioredis") logger.warning(f" 或者运行 'pip install -r backend/requirements.txt' 安装所有依赖") app = FastAPI( title="Auto Trade System API", version="1.0.0", description="币安自动交易系统API", redirect_slashes=False # 禁用自动重定向,避免307重定向问题 ) # CORS配置(允许React前端访问) # 默认包含:本地开发端口、主前端域名、推荐查看器域名 cors_origins_str = os.getenv('CORS_ORIGINS', 'http://localhost:3000,http://localhost:3001,http://localhost:5173,http://as.deepx1.com,http://asapi.deepx1.com,http://r.deepx1.com,https://r.deepx1.com') cors_origins = [origin.strip() for origin in cors_origins_str.split(',') if origin.strip()] logger.info(f"CORS允许的源: {cors_origins}") app.add_middleware( CORSMiddleware, allow_origins=cors_origins, allow_credentials=True, allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"], allow_headers=["*"], expose_headers=["*"], ) # 注册路由 app.include_router(config.router, prefix="/api/config", tags=["配置管理"]) app.include_router(trades.router, prefix="/api/trades", tags=["交易记录"]) app.include_router(stats.router, prefix="/api/stats", tags=["统计分析"]) app.include_router(dashboard.router, prefix="/api/dashboard", tags=["仪表板"]) app.include_router(account.router, prefix="/api/account", tags=["账户数据"]) app.include_router(recommendations.router, tags=["交易推荐"]) @app.get("/") async def root(): return { "message": "Auto Trade System API", "version": "1.0.0", "docs": "/docs" } @app.get("/api/health") async def health(): return {"status": "ok"} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8001)