config_manager.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import json
  2. import os
  3. from pathlib import Path
  4. from typing import Dict, Any, Optional, Union, List
  5. import yaml
  6. # 全局配置字典
  7. _CONFIG: Dict[str, Any] = {}
  8. # 默认配置
  9. DEFAULT_CONFIG = {
  10. # 数据处理配置
  11. "processing": {
  12. "use_parallel": True,
  13. "max_workers": None, # None表示使用CPU核心数
  14. "batch_size": 10000,
  15. "use_vectorized": True
  16. },
  17. # 数据库配置
  18. "database": {
  19. "batch_query_size": 10000,
  20. "use_parallel_query": True,
  21. "max_db_workers": None
  22. },
  23. # 插件配置
  24. "plugins": {
  25. "enabled": True,
  26. "auto_discover": True
  27. },
  28. # 日志配置
  29. "logging": {
  30. "level": "INFO",
  31. "log_to_file": True,
  32. "log_dir": "logs"
  33. },
  34. # 坐标系配置
  35. "coordinates": {
  36. "utm_zone": 51,
  37. "x_offset": 0.0,
  38. "y_offset": 0.0
  39. },
  40. # 文件路径配置
  41. "paths": {
  42. "resources_dir": "resources",
  43. "plugins_dir": "plugins",
  44. "output_dir": "output",
  45. "engine_path": "_internal/engine",
  46. "map_path": "_internal/data_map",
  47. "dbc_path": "_internal/VBox.dbc"
  48. }
  49. }
  50. def load_config(config_path: Optional[Union[str, Path]] = None) -> Dict[str, Any]:
  51. """加载配置文件
  52. Args:
  53. config_path: 配置文件路径,支持JSON和YAML格式
  54. Returns:
  55. 配置字典
  56. """
  57. global _CONFIG
  58. # 首先使用默认配置
  59. _CONFIG = DEFAULT_CONFIG.copy()
  60. if config_path is None:
  61. # 尝试查找默认配置文件
  62. default_paths = [
  63. Path("config.json"),
  64. Path("config.yaml"),
  65. Path("config.yml"),
  66. Path("config/config.json"),
  67. Path("config/config.yaml"),
  68. Path("config/config.yml")
  69. ]
  70. for path in default_paths:
  71. if path.exists():
  72. config_path = path
  73. break
  74. if config_path is None:
  75. print("未找到配置文件,使用默认配置")
  76. return _CONFIG
  77. # 确保config_path是Path对象
  78. if isinstance(config_path, str):
  79. config_path = Path(config_path)
  80. if not config_path.exists():
  81. print(f"配置文件不存在: {config_path},使用默认配置")
  82. return _CONFIG
  83. try:
  84. # 根据文件扩展名选择解析方法
  85. suffix = config_path.suffix.lower()
  86. if suffix in [".yaml", ".yml"]:
  87. with open(config_path, "r", encoding="utf-8") as f:
  88. user_config = yaml.safe_load(f)
  89. elif suffix == ".json":
  90. with open(config_path, "r", encoding="utf-8") as f:
  91. user_config = json.load(f)
  92. else:
  93. print(f"不支持的配置文件格式: {suffix},使用默认配置")
  94. return _CONFIG
  95. # 递归合并配置
  96. _CONFIG = _merge_configs(_CONFIG, user_config)
  97. print(f"成功加载配置文件: {config_path}")
  98. except Exception as e:
  99. print(f"加载配置文件失败: {e}")
  100. return _CONFIG
  101. def _merge_configs(base: Dict[str, Any], override: Dict[str, Any]) -> Dict[str, Any]:
  102. """递归合并配置字典
  103. Args:
  104. base: 基础配置
  105. override: 覆盖配置
  106. Returns:
  107. 合并后的配置
  108. """
  109. result = base.copy()
  110. for key, value in override.items():
  111. # 如果两个都是字典,递归合并
  112. if key in result and isinstance(result[key], dict) and isinstance(value, dict):
  113. result[key] = _merge_configs(result[key], value)
  114. else:
  115. # 否则直接覆盖
  116. result[key] = value
  117. return result
  118. def get_config(section: Optional[str] = None) -> Any:
  119. """获取配置
  120. Args:
  121. section: 配置节名称,如果为None则返回整个配置字典
  122. Returns:
  123. 配置值或配置字典
  124. """
  125. global _CONFIG
  126. # 如果配置为空,加载默认配置
  127. if not _CONFIG:
  128. _CONFIG = DEFAULT_CONFIG.copy()
  129. if section is None:
  130. return _CONFIG
  131. # 支持点号分隔的多级配置访问,如 "database.batch_query_size"
  132. if "." in section:
  133. parts = section.split(".")
  134. current = _CONFIG
  135. for part in parts:
  136. if part in current:
  137. current = current[part]
  138. else:
  139. print(f"配置节不存在: {section}")
  140. return None
  141. return current
  142. # 单级配置访问
  143. return _CONFIG.get(section)
  144. def set_config(section: str, value: Any) -> None:
  145. """设置配置
  146. Args:
  147. section: 配置节名称,支持点号分隔的多级配置
  148. value: 配置值
  149. """
  150. global _CONFIG
  151. # 如果配置为空,加载默认配置
  152. if not _CONFIG:
  153. _CONFIG = DEFAULT_CONFIG.copy()
  154. # 支持点号分隔的多级配置设置
  155. if "." in section:
  156. parts = section.split(".")
  157. current = _CONFIG
  158. # 遍历到倒数第二级
  159. for part in parts[:-1]:
  160. # 如果中间节点不存在或不是字典,创建新字典
  161. if part not in current or not isinstance(current[part], dict):
  162. current[part] = {}
  163. current = current[part]
  164. # 设置最后一级的值
  165. current[parts[-1]] = value
  166. else:
  167. # 单级配置设置
  168. _CONFIG[section] = value
  169. def save_config(config_path: Union[str, Path], format: str = "json") -> bool:
  170. """保存配置到文件
  171. Args:
  172. config_path: 配置文件路径
  173. format: 文件格式,支持 "json" 和 "yaml"
  174. Returns:
  175. 是否保存成功
  176. """
  177. global _CONFIG
  178. # 确保config_path是Path对象
  179. if isinstance(config_path, str):
  180. config_path = Path(config_path)
  181. # 确保目录存在
  182. config_path.parent.mkdir(parents=True, exist_ok=True)
  183. try:
  184. # 根据格式选择保存方法
  185. if format.lower() == "yaml":
  186. with open(config_path, "w", encoding="utf-8") as f:
  187. yaml.dump(_CONFIG, f, default_flow_style=False, sort_keys=False)
  188. else: # 默认使用JSON
  189. with open(config_path, "w", encoding="utf-8") as f:
  190. json.dump(_CONFIG, f, indent=2, ensure_ascii=False)
  191. print(f"配置已保存到: {config_path}")
  192. return True
  193. except Exception as e:
  194. print(f"保存配置失败: {e}")
  195. return False
  196. def update_config(new_config: Dict[str, Any]) -> None:
  197. """更新全局配置
  198. Args:
  199. new_config: 新的配置字典,将与现有配置合并
  200. """
  201. global _CONFIG
  202. _CONFIG = _merge_configs(_CONFIG, new_config)
  203. print("配置已更新")
  204. # 初始化时加载配置
  205. load_config()