Files
Feeding_control_system/common/ini_handler.py
2025-10-31 14:30:42 +08:00

278 lines
8.8 KiB
Python
Raw 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
from typing import Dict, Any, Optional, List
class IniHandlerError(Exception):
"""INI处理器异常基类"""
def __init__(self, message: str, file_path: str = None):
self.file_path = file_path
if file_path:
message = f"{message} (文件: {file_path})"
super().__init__(message)
class IniHandler:
"""
INI文件操作处理器基于文件路径的缓存
"""
_instances = {} # 按文件路径缓存的实例
def __new__(cls, file_path: str):
if file_path not in cls._instances:
instance = super().__new__(cls)
instance._file_path = file_path
instance._config = None # 单个文件的配置对象
cls._instances[file_path] = instance
return cls._instances[file_path]
def __init__(self, file_path: str):
"""
初始化INI处理器
Args:
file_path: INI文件路径
"""
# 文件路径已经在__new__中设置这里不需要重复设置
pass
def load_config(self) -> configparser.ConfigParser:
"""
加载并缓存INI配置文件
"""
if self._config is not None:
return self._config
if not os.path.exists(self._file_path):
raise IniHandlerError("INI文件不存在", self._file_path)
try:
config = configparser.ConfigParser()
config.read(self._file_path, encoding='utf-8')
self._config = config
return config
except Exception as e:
raise IniHandlerError(f"读取INI文件失败: {e}", self._file_path)
def get_value(self, section: str, option: str) -> Any:
"""
获取INI文件中的值
Args:
section: 节名
option: 选项名
default: 默认值
Returns:
获取的值,如果不存在则返回默认值
"""
try:
config = self.load_config()
if config.has_section(section) and config.has_option(section, option):
return config.get(section, option)
except IniHandlerError:
# 文件不存在或读取失败时返回默认值
return default
except Exception as e:
raise IniHandlerError(f"获取INI值失败: {e}", self._file_path)
def get_int_value(self, section: str, option: str) -> int:
"""
获取INI文件中的整数值
Args:
section: 节名
option: 选项名
default: 默认值
Returns:
获取的整数值,如果不存在或转换失败则返回默认值
"""
try:
config = self.load_config()
if config.has_section(section) and config.has_option(section, option):
return config.getint(section, option)
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"获取INI整数值失败: {e}", self._file_path)
def get_float_value(self, section: str, option: str) -> float:
"""
获取INI文件中的浮点数值
Args:
section: 节名
option: 选项名
default: 默认值
Returns:
获取的浮点数值,如果不存在或转换失败则返回默认值
"""
try:
config = self.load_config()
if config.has_section(section) and config.has_option(section, option):
return config.getfloat(section, option)
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"获取INI浮点数值失败: {e}", self._file_path)
def get_boolean_value(self, section: str, option: str) -> bool:
"""
获取INI文件中的布尔值
Args:
section: 节名
option: 选项名
default: 默认值
Returns:
获取的布尔值,如果不存在或转换失败则返回默认值
"""
try:
config = self.load_config()
if config.has_section(section) and config.has_option(section, option):
return config.getboolean(section, option)
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"获取INI布尔值失败: {e}", self._file_path)
def get_section(self, section: str) -> Dict[str, str]:
"""
获取INI文件中的整个节
Args:
section: 节名
Returns:
节中所有键值对的字典,如果节不存在则返回空字典
"""
try:
config = self.load_config()
if config.has_section(section):
return dict(config[section])
return {}
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"获取INI节失败: {e}", self._file_path)
def get_sections(self) -> List[str]:
"""
获取INI文件中的所有节名
Returns:
节名列表
"""
try:
config = self.load_config()
return config.sections()
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"获取INI节名列表失败: {e}", self._file_path)
def remove_section(self, section: str) -> None:
"""
移除INI文件中的节
Args:
section: 节名
"""
try:
config = self.load_config()
if config.has_section(section):
config.remove_section(section)
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"移除INI节失败: {e}", self._file_path)
def remove_option(self, section: str, option: str) -> None:
"""
移除INI文件中的选项
Args:
section: 节名
option: 选项名
"""
try:
config = self.load_config()
if config.has_section(section) and config.has_option(section, option):
config.remove_option(section, option)
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"移除INI选项失败: {e}", self._file_path)
def has_section(self, section: str) -> bool:
"""
检查INI文件中是否存在指定的节
Args:
section: 节名
Returns:
bool: 是否存在
"""
try:
config = self.load_config()
return config.has_section(section)
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"检查INI节失败: {e}", self._file_path)
def has_option(self, section: str, option: str) -> bool:
"""
检查INI文件中是否存在指定的选项
Args:
section: 节名
option: 选项名
Returns:
bool: 是否存在
"""
try:
config = self.load_config()
return config.has_option(section, option)
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"检查INI选项失败: {e}", self._file_path)
def write_ini_file(self) -> bool:
"""
写入INI文件持久化,写入前先set_value,set_value设置1或多个值后调用此方法
Returns:
bool: 是否写入成功
"""
try:
# 确保目录存在
dir_path = os.path.dirname(self._file_path)
if dir_path and not os.path.exists(dir_path):
os.makedirs(dir_path)
# 写入文件
with open(self._file_path, 'w', encoding='utf-8') as f:
self._config.write(f)
return True
except Exception as e:
raise IniHandlerError(f"写入INI文件失败: {e}", self._file_path)
def set_value(self, section: str, option: str, value: Any) -> None:
"""
设置INI文件中的值
Args:
section: 节名
option: 选项名
value: 要设置的值
"""
try:
config = self.load_config()
if not config.has_section(section):
config.add_section(section)
config.set(section, option, str(value))
except IniHandlerError:
raise
except Exception as e:
raise IniHandlerError(f"设置INI值失败: {e}", self._file_path)