orc-order-v2/app/config/settings.py
houhuan b7bce93995 refactor: 重构文件读取和日志处理以提升性能和稳定性
- 新增 smart_read_excel 工具函数,统一 Excel 读取逻辑并自动选择引擎
- 重构 ConfigManager.get_path 方法,使用 pathlib 提升路径处理可靠性
- 将 GUI 日志处理改为异步队列模式,避免 UI 阻塞
- 优化 ExcelProcessor 的表头识别逻辑,避免重复读取文件
- 更新配置文件中的版本号
2026-03-30 11:17:25 +08:00

145 lines
5.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
配置管理模块
-----------
提供统一的配置加载、访问和保存功能。
"""
import os
import configparser
import logging
from typing import Dict, List, Optional, Any
from .defaults import DEFAULT_CONFIG
logger = logging.getLogger(__name__)
class ConfigManager:
"""
配置管理类,负责加载和保存配置
单例模式确保全局只有一个配置实例
"""
_instance = None
def __new__(cls, config_file=None):
"""单例模式实现"""
if cls._instance is None:
cls._instance = super(ConfigManager, cls).__new__(cls)
cls._instance._init(config_file)
return cls._instance
def _init(self, config_file):
"""初始化配置管理器"""
self.config_file = config_file or 'config.ini'
self.config = configparser.ConfigParser()
self.load_config()
def load_config(self) -> None:
"""
加载配置文件,如果不存在则创建默认配置
"""
if not os.path.exists(self.config_file):
self.create_default_config()
else:
try:
# 先读取现有配置
self.config.read(self.config_file, encoding='utf-8')
# 检查是否有缺失的配置项,只添加缺失的项
for section, options in DEFAULT_CONFIG.items():
if not self.config.has_section(section):
self.config.add_section(section)
for option, value in options.items():
if not self.config.has_option(section, option):
self.config.set(section, option, value)
# 保存更新后的配置
self.save_config()
logger.info(f"已加载并更新配置文件: {self.config_file}")
except Exception as e:
logger.error(f"加载配置文件时出错: {e}")
logger.info("使用默认配置")
self.create_default_config(save=False)
def create_default_config(self, save: bool = True) -> None:
"""创建默认配置"""
for section, options in DEFAULT_CONFIG.items():
if not self.config.has_section(section):
self.config.add_section(section)
for option, value in options.items():
self.config.set(section, option, value)
if save:
self.save_config()
logger.info(f"已创建默认配置文件: {self.config_file}")
def save_config(self) -> None:
"""保存配置到文件"""
try:
with open(self.config_file, 'w', encoding='utf-8') as f:
self.config.write(f)
logger.info(f"配置已保存到: {self.config_file}")
except Exception as e:
logger.error(f"保存配置文件时出错: {e}")
def get(self, section: str, option: str, fallback: Any = None) -> Any:
"""获取配置值"""
return self.config.get(section, option, fallback=fallback)
def getint(self, section: str, option: str, fallback: int = 0) -> int:
"""获取整数配置值"""
return self.config.getint(section, option, fallback=fallback)
def getfloat(self, section: str, option: str, fallback: float = 0.0) -> float:
"""获取浮点数配置值"""
return self.config.getfloat(section, option, fallback=fallback)
def getboolean(self, section: str, option: str, fallback: bool = False) -> bool:
"""获取布尔配置值"""
return self.config.getboolean(section, option, fallback=fallback)
def get_list(self, section: str, option: str, fallback: str = "", delimiter: str = ",") -> List[str]:
"""获取列表配置值(逗号分隔的字符串转为列表)"""
value = self.get(section, option, fallback)
return [item.strip() for item in value.split(delimiter) if item.strip()]
def update(self, section: str, option: str, value: Any) -> None:
"""更新配置选项"""
if not self.config.has_section(section):
self.config.add_section(section)
self.config.set(section, option, str(value))
logger.debug(f"更新配置: [{section}] {option} = {value}")
def get_path(self, section: str, option: str, fallback: str = "", create: bool = False) -> str:
"""
获取路径配置并确保它是一个有效的绝对路径
如果create为True则自动创建该目录
"""
from pathlib import Path
path_str = self.get(section, option, fallback)
path = Path(path_str)
if not path.is_absolute():
# 相对路径,转为绝对路径(相对于项目根目录)
path = Path(os.getcwd()) / path
if create:
try:
# 智能判断是文件还是目录
# 如果有后缀名则认为是文件,创建其父目录
if path.suffix:
directory = path.parent
if not directory.exists():
directory.mkdir(parents=True, exist_ok=True)
logger.info(f"已创建父目录: {directory}")
else:
# 否则认为是目录路径
if not path.exists():
path.mkdir(parents=True, exist_ok=True)
logger.info(f"已创建目录: {path}")
except Exception as e:
logger.error(f"创建目录失败: {path}, 错误: {e}")
return str(path.absolute())