# E:\AI_System\core\config.py
import os
import yaml
from pathlib import Path
from typing import Any, Dict, Optional, Union
import logging
from .exceptions import ConfigError
class ConfigManager:
"""配置管理系统,支持环境变量、配置文件和默认值"""
def __init__(self, base_dir: str, env_prefix: str = "AI_SYSTEM_"):
"""
初始化配置管理器
Args:
base_dir: 基础目录路径
env_prefix: 环境变量前缀
"""
self.base_dir = Path(base_dir)
self.env_prefix = env_prefix
self.config = {}
self.logger = logging.getLogger("ConfigManager")
# 创建必要目录
self._create_necessary_dirs()
# 加载配置
self._load_config()
def _create_necessary_dirs(self):
"""创建系统必需的目录结构"""
required_dirs = [
self.base_dir / "data",
self.base_dir / "logs",
self.base_dir / "config",
self.base_dir / "models",
self.base_dir / "cache"
]
for dir_path in required_dirs:
dir_path.mkdir(parents=True, exist_ok=True)
self.logger.info(f"确保目录存在: {dir_path}")
def _load_config(self):
"""加载配置 - 优先级:环境变量 > 配置文件 > 默认值"""
# 1. 加载默认配置
self.config = self._get_default_config()
# 2. 加载配置文件
config_path = self.base_dir / "config" / "system_config.yaml"
if config_path.exists():
try:
with open(config_path, 'r', encoding='utf-8') as f:
file_config = yaml.safe_load(f) or {}
self._merge_config(file_config)
self.logger.info(f"从文件加载配置: {config_path}")
except Exception as e:
self.logger.error(f"配置文件解析错误: {str(e)}")
raise ConfigError(f"配置文件解析错误: {str(e)}")
else:
self.logger.warning(f"配置文件不存在: {config_path}")
# 3. 加载环境变量
self._load_env_vars()
# 4. 验证必需配置项
self._validate_required_config()
def _get_default_config(self) -> Dict[str, Any]:
"""获取默认配置"""
return {
# 系统核心配置
"SYSTEM_NAME": "AI_System",
"LOG_LEVEL": "INFO",
"LOG_DIR": str(self.base_dir / "logs"),
# 线程和进程配置
"MAX_WORKERS": max(1, os.cpu_count() * 2), # 默认CPU核心数*2
"MAX_THREADS_PER_WORKER": 10,
# 网络配置
"API_HOST": "0.0.0.0",
"API_PORT": 5000,
"API_TIMEOUT": 30,
# 资源限制
"MEMORY_LIMIT_MB": 4096,
"CPU_LIMIT_PERCENT": 80,
# 智能体配置
"AGENT_TYPE": "autonomous",
"AGENT_UPDATE_INTERVAL": 60, # 秒
"AGENT_MAX_TASKS": 100,
# 数据库配置
"DB_PATH": str(self.base_dir / "data" / "system.db"),
"DB_BACKUP_INTERVAL": 3600, # 秒
# 调试配置
"DEBUG_MODE": False,
"PROFILE_PERFORMANCE": False
}
def _merge_config(self, new_config: Dict[str, Any]):
"""合并配置(递归更新字典)"""
def merge_dict(base: Dict, update: Dict):
for key, value in update.items():
if isinstance(value, dict) and key in base and isinstance(base[key], dict):
merge_dict(base[key], value)
else:
base[key] = value
merge_dict(self.config, new_config)
def _load_env_vars(self):
"""从环境变量加载配置"""
for key, value in self.config.items():
env_key = f"{self.env_prefix}{key}"
env_value = os.environ.get(env_key)
if env_value is not None:
# 尝试转换类型
if isinstance(value, bool):
self.config[key] = env_value.lower() in ('true', '1', 'yes')
elif isinstance(value, int):
try:
self.config[key] = int(env_value)
except ValueError:
self.logger.warning(f"环境变量 {env_key} 无法转换为整数: {env_value}")
elif isinstance(value, float):
try:
self.config[key] = float(env_value)
except ValueError:
self.logger.warning(f"环境变量 {env_key} 无法转换为浮点数: {env_value}")
else:
self.config[key] = env_value
self.logger.info(f"从环境变量加载: {key}={self.config[key]}")
def _validate_required_config(self):
"""验证必需配置项是否存在"""
required_keys = [
"MAX_WORKERS", "API_HOST", "API_PORT",
"DB_PATH", "LOG_DIR", "LOG_LEVEL"
]
missing_keys = [key for key in required_keys if key not in self.config]
if missing_keys:
error_msg = f"缺少必需配置项: {', '.join(missing_keys)}"
self.logger.error(error_msg)
raise ConfigError(error_msg)
def get(self, key: str, default: Optional[Any] = None) -> Any:
"""获取配置值"""
return self.config.get(key, default)
def __getattr__(self, key: str) -> Any:
"""通过属性访问配置"""
if key in self.config:
return self.config[key]
raise AttributeError(f"配置项 '{key}' 不存在")
def __getitem__(self, key: str) -> Any:
"""通过索引访问配置"""
if key in self.config:
return self.config[key]
raise KeyError(f"配置项 '{key}' 不存在")
def __contains__(self, key: str) -> bool:
"""检查配置项是否存在"""
return key in self.config
def save_config(self, file_path: Optional[Union[str, Path]] = None):
"""保存当前配置到文件"""
if file_path is None:
file_path = self.base_dir / "config" / "system_config.yaml"
file_path = Path(file_path)
file_path.parent.mkdir(parents=True, exist_ok=True)
try:
with open(file_path, 'w', encoding='utf-8') as f:
yaml.safe_dump(self.config, f, sort_keys=False, allow_unicode=True)
self.logger.info(f"配置已保存到: {file_path}")
return True
except Exception as e:
self.logger.error(f"保存配置失败: {str(e)}")
return False
def reload(self):
"""重新加载配置"""
self.logger.info("重新加载配置...")
self._load_config()
self.logger.info("配置重新加载完成")
def print_config(self, show_all: bool = False):
"""打印当前配置(安全地隐藏敏感信息)"""
sensitive_keys = ["API_KEY", "DB_PASSWORD", "SECRET_KEY"]
print("\n当前系统配置:")
for key, value in self.config.items():
if key in sensitive_keys and not show_all:
print(f"{key}: {'*' * 8}")
else:
print(f"{key}: {value}")
print()
# 全局配置实例
_system_config = None
def get_config(base_dir: Optional[str] = None, env_prefix: str = "AI_SYSTEM_") -> ConfigManager:
"""获取全局配置实例(单例模式)"""
global _system_config
if _system_config is None:
if base_dir is None:
# 尝试从环境变量获取基础目录
base_dir = os.environ.get(f"{env_prefix}BASE_DIR", os.getcwd())
_system_config = ConfigManager(base_dir=base_dir, env_prefix=env_prefix)
return _system_config
# 示例使用
if __name__ == "__main__":
# 初始化配置
config = get_config(base_dir=os.getcwd())
# 访问配置
print("API端口:", config.API_PORT)
print("最大工作线程数:", config.MAX_WORKERS)
# 打印配置
config.print_config()
# 保存配置
config.save_config()
# 测试代码
def test_config_system():
# 设置测试环境变量
os.environ["AI_SYSTEM_API_PORT"] = "8080"
os.environ["AI_SYSTEM_DEBUG_MODE"] = "true"
# 创建临时目录
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
# 创建配置文件
config_path = Path(tmpdir) / "config" / "system_config.yaml"
config_path.parent.mkdir(parents=True, exist_ok=True)
with open(config_path, 'w') as f:
f.write("MAX_WORKERS: 16\nLOG_LEVEL: DEBUG")
# 初始化配置
config = ConfigManager(base_dir=tmpdir, env_prefix="AI_SYSTEM_")
# 验证配置
assert config.API_PORT == 8080 # 来自环境变量
assert config.MAX_WORKERS == 16 # 来自配置文件
assert config.DEBUG_MODE is True # 环境变量转换
assert config.LOG_LEVEL == "DEBUG" # 来自配置文件
# 测试默认值
assert config.MEMORY_LIMIT_MB == 4096 # 默认值
print("所有测试通过!")
if __name__ == "__main__":
test_config_system()
# E:\AI_System\core\config.py
import os
import yaml
from pathlib import Path
from typing import Any, Dict, Optional, Union
import logging
from .exceptions import ConfigError
class ConfigManager:
"""配置管理系统,支持环境变量、配置文件和默认值"""
def __init__(self, base_dir: str, env_prefix: str = "AI_SYSTEM_"):
"""
初始化配置管理器
Args:
base_dir: 基础目录路径
env_prefix: 环境变量前缀
"""
self.base_dir = Path(base_dir)
self.env_prefix = env_prefix
self.config = {}
self.logger = logging.getLogger("ConfigManager")
# 创建必要目录
self._create_necessary_dirs()
# 加载配置
self._load_config()
def _create_necessary_dirs(self):
"""创建系统必需的目录结构"""
required_dirs = [
self.base_dir / "data",
self.base_dir / "logs",
self.base_dir / "config",
self.base_dir / "models",
self.base_dir / "cache"
]
for dir_path in required_dirs:
dir_path.mkdir(parents=True, exist_ok=True)
self.logger.info(f"确保目录存在: {dir_path}")
def _load_config(self):
"""加载配置 - 优先级:环境变量 > 配置文件 > 默认值"""
# 1. 加载默认配置
self.config = self._get_default_config()
# 2. 加载配置文件
config_path = self.base_dir / "config" / "system_config.yaml"
if config_path.exists():
try:
with open(config_path, 'r', encoding='utf-8') as f:
file_config = yaml.safe_load(f) or {}
self._merge_config(file_config)
self.logger.info(f"从文件加载配置: {config_path}")
except Exception as e:
self.logger.error(f"配置文件解析错误: {str(e)}")
raise ConfigError(f"配置文件解析错误: {str(e)}")
else:
self.logger.warning(f"配置文件不存在: {config_path}")
# 3. 加载环境变量
self._load_env_vars()
# 4. 验证必需配置项
self._validate_required_config()
def _get_default_config(self) -> Dict[str, Any]:
"""获取默认配置"""
return {
# 系统核心配置
"SYSTEM_NAME": "AI_System",
"LOG_LEVEL": "INFO",
"LOG_DIR": str(self.base_dir / "logs"),
# 线程和进程配置
"MAX_WORKERS": max(1, os.cpu_count() * 2), # 默认CPU核心数*2
"MAX_THREADS_PER_WORKER": 10,
# 网络配置
"API_HOST": "0.0.0.0",
"API_PORT": 5000,
"API_TIMEOUT": 30,
# 资源限制
"MEMORY_LIMIT_MB": 4096,
"CPU_LIMIT_PERCENT": 80,
# 智能体配置
"AGENT_TYPE": "autonomous",
"AGENT_UPDATE_INTERVAL": 60, # 秒
"AGENT_MAX_TASKS": 100,
# 数据库配置
"DB_PATH": str(self.base_dir / "data" / "system.db"),
"DB_BACKUP_INTERVAL": 3600, # 秒
# 调试配置
"DEBUG_MODE": False,
"PROFILE_PERFORMANCE": False
}
def _merge_config(self, new_config: Dict[str, Any]):
"""合并配置(递归更新字典)"""
def merge_dict(base: Dict, update: Dict):
for key, value in update.items():
if isinstance(value, dict) and key in base and isinstance(base[key], dict):
merge_dict(base[key], value)
else:
base[key] = value
merge_dict(self.config, new_config)
def _load_env_vars(self):
"""从环境变量加载配置"""
for key, value in self.config.items():
env_key = f"{self.env_prefix}{key}"
env_value = os.environ.get(env_key)
if env_value is not None:
# 尝试转换类型
if isinstance(value, bool):
self.config[key] = env_value.lower() in ('true', '1', 'yes')
elif isinstance(value, int):
try:
self.config[key] = int(env_value)
except ValueError:
self.logger.warning(f"环境变量 {env_key} 无法转换为整数: {env_value}")
elif isinstance(value, float):
try:
self.config[key] = float(env_value)
except ValueError:
self.logger.warning(f"环境变量 {env_key} 无法转换为浮点数: {env_value}")
else:
self.config[key] = env_value
self.logger.info(f"从环境变量加载: {key}={self.config[key]}")
def _validate_required_config(self):
"""验证必需配置项是否存在"""
required_keys = [
"MAX_WORKERS", "API_HOST", "API_PORT",
"DB_PATH", "LOG_DIR", "LOG_LEVEL"
]
missing_keys = [key for key in required_keys if key not in self.config]
if missing_keys:
error_msg = f"缺少必需配置项: {', '.join(missing_keys)}"
self.logger.error(error_msg)
raise ConfigError(error_msg)
def get(self, key: str, default: Optional[Any] = None) -> Any:
"""获取配置值"""
return self.config.get(key, default)
def __getattr__(self, key: str) -> Any:
"""通过属性访问配置"""
if key in self.config:
return self.config[key]
raise AttributeError(f"配置项 '{key}' 不存在")
def __getitem__(self, key: str) -> Any:
"""通过索引访问配置"""
if key in self.config:
return self.config[key]
raise KeyError(f"配置项 '{key}' 不存在")
def __contains__(self, key: str) -> bool:
"""检查配置项是否存在"""
return key in self.config
def save_config(self, file_path: Optional[Union[str, Path]] = None):
"""保存当前配置到文件"""
if file_path is None:
file_path = self.base_dir / "config" / "system_config.yaml"
file_path = Path(file_path)
file_path.parent.mkdir(parents=True, exist_ok=True)
try:
with open(file_path, 'w', encoding='utf-8') as f:
yaml.safe_dump(self.config, f, sort_keys=False, allow_unicode=True)
self.logger.info(f"配置已保存到: {file_path}")
return True
except Exception as e:
self.logger.error(f"保存配置失败: {str(e)}")
return False
def reload(self):
"""重新加载配置"""
self.logger.info("重新加载配置...")
self._load_config()
self.logger.info("配置重新加载完成")
def print_config(self, show_all: bool = False):
"""打印当前配置(安全地隐藏敏感信息)"""
sensitive_keys = ["API_KEY", "DB_PASSWORD", "SECRET_KEY"]
print("\n当前系统配置:")
for key, value in self.config.items():
if key in sensitive_keys and not show_all:
print(f"{key}: {'*' * 8}")
else:
print(f"{key}: {value}")
print()
# 全局配置实例
_system_config = None
def get_config(base_dir: Optional[str] = None, env_prefix: str = "AI_SYSTEM_") -> ConfigManager:
"""获取全局配置实例(单例模式)"""
global _system_config
if _system_config is None:
if base_dir is None:
# 尝试从环境变量获取基础目录
base_dir = os.environ.get(f"{env_prefix}BASE_DIR", os.getcwd())
_system_config = ConfigManager(base_dir=base_dir, env_prefix=env_prefix)
return _system_config
# 示例使用
if __name__ == "__main__":
# 初始化配置
config = get_config(base_dir=os.getcwd())
# 访问配置
print("API端口:", config.API_PORT)
print("最大工作线程数:", config.MAX_WORKERS)
# 打印配置
config.print_config()
# 保存配置
config.save_config()
# 测试代码
def test_config_system():
# 设置测试环境变量
os.environ["AI_SYSTEM_API_PORT"] = "8080"
os.environ["AI_SYSTEM_DEBUG_MODE"] = "true"
# 创建临时目录
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
# 创建配置文件
config_path = Path(tmpdir) / "config" / "system_config.yaml"
config_path.parent.mkdir(parents=True, exist_ok=True)
with open(config_path, 'w') as f:
f.write("MAX_WORKERS: 16\nLOG_LEVEL: DEBUG")
# 初始化配置
config = ConfigManager(base_dir=tmpdir, env_prefix="AI_SYSTEM_")
# 验证配置
assert config.API_PORT == 8080 # 来自环境变量
assert config.MAX_WORKERS == 16 # 来自配置文件
assert config.DEBUG_MODE is True # 环境变量转换
assert config.LOG_LEVEL == "DEBUG" # 来自配置文件
# 测试默认值
assert config.MEMORY_LIMIT_MB == 4096 # 默认值
print("所有测试通过!")
if __name__ == "__main__":
test_config_system()
Microsoft Windows [版本 10.0.22631.2861]
(c) Microsoft Corporation。保留所有权利。
C:\Users\Administrator>cd /d E:\AI_System\web_ui
E:\AI_System\web_ui>python server.py
Traceback (most recent call last):
File "E:\AI_System\web_ui\server.py", line 49, in <module>
from core.config import CoreConfig as SystemConfig
File "E:\AI_System\core\__init__.py", line 5, in <module>
from .config import CoreConfig
File "E:\AI_System\core\config.py", line 7, in <module>
from .exceptions import ConfigError
ImportError: cannot import name 'ConfigError' from 'core.exceptions' (E:\AI_System\core\exceptions.py)
E:\AI_System\web_ui>