106 lines
3.3 KiB
Python
106 lines
3.3 KiB
Python
import os
|
||
from pathlib import Path
|
||
from types import SimpleNamespace # 导入SimpleNamespace
|
||
from typing import Any, Dict
|
||
|
||
import yaml
|
||
from dotenv import load_dotenv
|
||
from loguru import logger
|
||
|
||
|
||
class EnvConfig:
|
||
def __init__(self):
|
||
# 加载环境变量
|
||
if os.path.exists(".env"):
|
||
if load_dotenv(".env"):
|
||
logger.info("[激活配置] .env 配置加载成功 ✅")
|
||
else:
|
||
# 将 exit(1) 更改为 warning,避免程序直接退出
|
||
logger.warning(
|
||
"[激活配置] 环境变量加载失败,请检查 .env 文件内容是否正确"
|
||
)
|
||
else:
|
||
logger.warning("[激活配置] .env 文件不存在,将不加载环境变量")
|
||
|
||
def _parse_bool(self, value):
|
||
"""将字符串形式的布尔值转换为布尔类型"""
|
||
if isinstance(value, str):
|
||
if value.lower() == "true":
|
||
return True
|
||
elif value.lower() == "false":
|
||
return False
|
||
return value
|
||
|
||
def __getattr__(self, name):
|
||
value = os.getenv(name)
|
||
if value is not None:
|
||
return self._parse_bool(value)
|
||
default_name = f"DEFAULT_{name}"
|
||
default_value = os.getenv(default_name)
|
||
if default_value is not None:
|
||
return self._parse_bool(default_value)
|
||
return None
|
||
|
||
def get(self, name, default=None):
|
||
value = os.getenv(name)
|
||
if value is not None:
|
||
return self._parse_bool(value)
|
||
return default
|
||
|
||
|
||
class YamlConfig:
|
||
def __init__(self, yaml_file: str = "config.yaml"):
|
||
self._yaml_file = Path(yaml_file)
|
||
self._load_settings()
|
||
|
||
def _load_settings(self) -> None:
|
||
if not self._yaml_file.exists():
|
||
raise FileNotFoundError(f"[激活配置] 配置文件 {self._yaml_file} 不存在")
|
||
|
||
with open(self._yaml_file, "r", encoding="utf-8") as f:
|
||
config_data = yaml.safe_load(f) or {}
|
||
|
||
self._set_attributes(config_data)
|
||
logger.info("[激活配置] config.yaml 配置加载成功 ✅")
|
||
|
||
def _set_attributes(self, config_data: Dict[str, Any]) -> None:
|
||
# 使用 SimpleNamespace 更好地处理嵌套配置,使其可以通过属性访问
|
||
for key, value in config_data.items():
|
||
if isinstance(value, dict):
|
||
setattr(self, key, SimpleNamespace(**value))
|
||
else:
|
||
setattr(self, key, value)
|
||
|
||
# 移除 _from_dict 方法,因为 SimpleNamespace 可以直接从字典创建
|
||
|
||
def __repr__(self) -> str:
|
||
attrs = []
|
||
for key in sorted(self.__dict__.keys()):
|
||
if not key.startswith("_"):
|
||
value = getattr(self, key)
|
||
attrs.append(f"{key}={repr(value)}")
|
||
return f"Settings({', '.join(attrs)})"
|
||
|
||
def reload(self) -> None:
|
||
if self._yaml_file is None:
|
||
raise RuntimeError("无法重新加载,此实例是从字典创建的")
|
||
self._load_settings()
|
||
|
||
|
||
# 创建配置实例
|
||
env_config = EnvConfig()
|
||
yaml_config = None
|
||
try:
|
||
yaml_config = YamlConfig()
|
||
except FileNotFoundError:
|
||
logger.warning("[激活配置] 配置文件 config.yaml 不存在,将不加载配置")
|
||
|
||
|
||
class Setting:
|
||
def __init__(self):
|
||
self.env = env_config
|
||
self.config = yaml_config
|
||
|
||
|
||
setting = Setting()
|