Json-Python-Server/app/core/config.py

123 lines
4.3 KiB
Python
Raw Normal View History

2026-01-29 18:18:32 +08:00
"""
FastAPI 应用配置管理
支持环境变量配置生产级配置管理
"""
import os
from pathlib import Path
from typing import Optional
import logging
try:
from dotenv import load_dotenv
except Exception: # pragma: no cover
load_dotenv = None
# 项目根目录
BASE_DIR = Path(__file__).resolve().parent.parent.parent
# 加载 .env不覆盖已存在的系统环境变量
_dotenv_path = BASE_DIR / ".env"
if load_dotenv is not None and _dotenv_path.exists():
load_dotenv(dotenv_path=_dotenv_path, override=False)
# 环境变量
ENVIRONMENT = os.getenv('ENV', 'development')
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
class Settings:
"""应用配置类"""
# FastAPI 基础配置
APP_TITLE = "时间序列数据分析系统"
APP_DESCRIPTION = "支持多格式数据上传、AI增强分析、多语言报告生成"
APP_VERSION = "2.0.0"
# API 暴露模式
# - full: 暴露 v1 + v2默认
# - v2: 仅暴露 v2 分析接口 + 基础状态接口(禁用 v1 上传/文件/图片接口)
API_MODE = os.getenv('API_MODE', 'full').strip().lower()
# 服务器配置
HOST = os.getenv('HOST', '0.0.0.0')
PORT = int(os.getenv('PORT', 60201))
RELOAD = DEBUG
# CORS 配置
CORS_ORIGINS = os.getenv('CORS_ORIGINS', '*').split(',')
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_METHODS = ['*']
CORS_ALLOW_HEADERS = ['*']
# 文件上传配置
UPLOAD_DIR = Path(os.getenv('UPLOAD_DIR', BASE_DIR / 'uploads'))
UPLOAD_DIR.mkdir(exist_ok=True)
MAX_UPLOAD_SIZE = int(os.getenv('MAX_UPLOAD_SIZE', 16 * 1024 * 1024)) # 16MB
ALLOWED_EXTENSIONS = {'csv'}
# 临时文件配置
TEMP_DIR = Path(os.getenv('TEMP_DIR', BASE_DIR / 'temp'))
TEMP_DIR.mkdir(exist_ok=True)
# 字体配置
FONTS_DIR = Path(os.getenv('FONTS_DIR', BASE_DIR / 'resource' / 'fonts'))
FONTS_DIR.mkdir(parents=True, exist_ok=True)
# API 配置 (阿里云千问)
API_KEY = os.getenv('MY_API_KEY', '')
API_BASE = os.getenv('MY_API_BASE', 'https://dashscope.aliyuncs.com/compatible-mode/v1')
API_MODEL = os.getenv('MY_MODEL', 'qwen-turbo')
API_TIMEOUT = int(os.getenv('API_TIMEOUT', 30))
# 分析配置
LANGUAGE_DEFAULT = os.getenv('LANGUAGE_DEFAULT', 'zh')
ANALYSIS_TIMEOUT = int(os.getenv('ANALYSIS_TIMEOUT', 300)) # 5分钟
# 日志配置
LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO' if not DEBUG else 'DEBUG')
LOG_DIR = Path(os.getenv('LOG_DIR', BASE_DIR / 'logs'))
LOG_DIR.mkdir(exist_ok=True)
# 内存管理
MAX_MEMORY_MB = int(os.getenv('MAX_MEMORY_MB', 500))
# v2 (OSS URL) 配置
# 允许的域名白名单(逗号分隔)。为空时表示不启用域名白名单(仍会做私网/环回 IP 拦截)。
V2_ALLOWED_HOSTS = [h.strip() for h in os.getenv('V2_ALLOWED_HOSTS', '').split(',') if h.strip()]
# 是否允许 http默认仅 https
V2_ALLOW_HTTP = os.getenv('V2_ALLOW_HTTP', 'False').lower() == 'true'
# 是否允许私网/环回地址(仅用于本地开发/冒烟;生产建议保持 False
V2_ALLOW_PRIVATE_NETWORKS = os.getenv('V2_ALLOW_PRIVATE_NETWORKS', 'False').lower() == 'true'
# 下载超时。requests 支持 (connect, read),这里统一使用 read 超时。
V2_DOWNLOAD_TIMEOUT_SECONDS = float(os.getenv('V2_DOWNLOAD_TIMEOUT_SECONDS', 30))
V2_CONNECT_TIMEOUT_SECONDS = float(os.getenv('V2_CONNECT_TIMEOUT_SECONDS', 5))
@classmethod
def get_upload_path(cls, filename: str) -> Path:
"""获取上传文件的完整路径"""
return cls.UPLOAD_DIR / filename
@classmethod
def get_temp_path(cls, filename: str) -> Path:
"""获取临时文件的完整路径"""
return cls.TEMP_DIR / filename
# 日志配置
def setup_logging():
"""设置日志系统"""
logging.basicConfig(
level=Settings.LOG_LEVEL,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(Settings.LOG_DIR / 'app.log'),
logging.StreamHandler()
]
)
# 创建全局配置实例
settings = Settings()
# 启用日志
setup_logging()