系统路径管理是 SunvStation 二次开发中的核心功能之一,它允许脚本动态访问系统配置文件、模板、脚本目录、临时文件目录等关键资源路径。通过统一的接口获取路径信息,可以确保脚本在不同安装环境和操作系统上的兼容性和可移植性。 ## 架构概览 系统路径管理通过 `ProjectMixin` 提供的 `getSysPathName(mode)` 方法实现,该方法封装了底层的 `GlobalOptions` 单例对象访问逻辑,根据模式参数返回不同类型的系统路径。以下展示了系统路径管理的调用层次结构: ```mermaid graph TD A[Python 脚本] -->|调用| B[SSProcess 实例] B -->|继承| C[ProjectMixin] C -->|提供方法| D[getSysPathName] D -->|使用| E[GlobalOptions 单例] D -->|mode=0| F[getConfigurePath] D -->|mode=1| G[getTemplatePath] D -->|mode=2| H[getCommonPath] D -->|mode=3| I[getSchemeFilePath] D -->|mode=4| J[getEpsTempPath] D -->|mode=5| K[getCurrentMap] D -->|mode=6| L[os.environ] D -->|mode=7/8| M[getSchemeFilePath] K -->|获取| N[getProjectName] N -->|Path.parent| O[工程目录] style B fill:#e1f5ff style C fill:#fff4e1 style E fill:#f0f0f0 ``` Sources: [PySSProcess.py](PySSProcess.py#L25-L50), [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L71-L116) ## 路径模式详解 `getSysPathName(mode)` 方法支持 9 种路径模式(0-8),每种模式对应不同类型的系统路径。理解这些路径模式的用途对于构建健壮的脚本至关重要。 ### 路径模式对照表 | 模式 | 路径类型 | 底层方法 | 说明 | 典型用途 | |-----|---------|---------|------|---------| | 0 | 配置路径 | `getConfigurePath()` | 存放系统配置文件(Windows 下为应用程序路径) | 读取 SSGlobal.xml 等配置文件 | | 1 | 模板路径 | `getTemplatePath()` | 存放地物模板文件 | 加载 .egdb 模板创建新工程 | | 2 | Comm 路径 | `getCommonPath()` | 公共资源目录 | 访问共享的数据符号库 | | 3 | Script 路径 | `getSchemeFilePath("scripts")` | 脚本文件目录 | 动态加载或引用其他脚本 | | 4 | SSTemp 路径 | `getEpsTempPath()` | 临时文件目录 | 存储中间处理结果 | | 5 | 工程文件路径 | `getCurrentMap().getProjectName()` | 当前工程文件所在目录 | 计算相对路径、保存输出 | | 6 | 系统目录 | `WINDIR` 或 `/usr` | 操作系统目录 | 访问系统级文件 | | 7 | 工作台面目录 | `getSchemeFilePath("")` | 用户工作台面根目录 | 访问用户自定义配置 | | 8 | 工作台面目录 | `getSchemeFilePath("")` | 用户工作台面根目录 | 同模式 7,保留兼容性 | Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L71-L116), [PySSWidget.py](PySSWidget.py#L1019-L1049), [PySSWidget.py](PySSWidget.py#L1059-L1065), [PySSWidget.py](PySSWidget.py#L1172-L1180) ### 路径特点说明 **配置路径(mode 0)**:在 Windows 系统中通常为应用程序安装目录,在 Unix 系统中可能为 `/etc` 或 `/opt` 等系统配置目录。此路径用于存放全局配置文件,如 `SSGlobal.xml`。 **模板路径(mode 1)**:存放预定义的地物模板文件(.egdb 格式)。当需要创建新的工程文件时,通常基于这些模板进行初始化。 **Comm 路径(mode 2)**:公共资源目录,包含符号库、样式表等跨工程共享的资源文件。 **Script 路径(mode 3)**:存放 Python 脚本文件的目录。此路径对于脚本间的相互引用(import)和动态加载(exec)非常重要。 **SSTemp 路径(mode 4)**:临时文件目录,用于存储处理过程中的临时数据。脚本完成后应清理此目录中的临时文件。 **工程文件路径(mode 5)**:返回当前打开的工程文件(.egdb)所在的父目录。如果当前没有工程或工程未保存,则返回空字符串。此路径对于保存输出文件、创建相对路径非常有用。 **系统目录(mode 6)**:根据操作系统类型返回不同的目录。Windows 下为 `%WINDIR%` 环境变量指向的目录(通常为 `C:\Windows`),Unix/Linux 下为 `/usr` 目录。 **工作台面目录(mode 7/8)**:返回当前激活的工作台面目录。工作台面是 SunvStation 的用户配置组织单位,不同的工作台面可以有独立的配置、脚本和模板。 Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L104-L116) ## 基本用法 ### 获取各类系统路径 最简单的用法是直接调用 `getSysPathName(mode)` 获取所需路径: ```python from sunvpy import SSProcess # 获取配置路径 config_path = SSProcess.getSysPathName(0) print(f"配置路径: {config_path}") # 获取模板路径 template_path = SSProcess.getSysPathName(1) print(f"模板路径: {template_path}") # 获取公共资源路径 common_path = SSProcess.getSysPathName(2) print(f"公共资源路径: {common_path}") # 获取脚本路径 script_path = SSProcess.getSysPathName(3) print(f"脚本路径: {script_path}") # 获取临时文件路径 temp_path = SSProcess.getSysPathName(4) print(f"临时文件路径: {temp_path}") ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L71-L116) ### 构造完整文件路径 获取路径后,可以使用路径构造功能完整的文件路径: ```python # 构造配置文件的完整路径 config_file = config_path + "system_config.xml" # 构造模板文件的完整路径 template_file = template_path + "standard_template.egdb" # 构造脚本文件的完整路径 script_file = script_path + "utility_functions.py" # 使用 pathlib 进行更安全的路径操作(推荐) from pathlib import Path config_file_safe = Path(config_path) / "system_config.xml" template_file_safe = Path(template_path) / "standard_template.egdb" script_file_safe = Path(script_path) / "utility_functions.py" ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L85-L98) ## 高级用法 ### 获取工程文件路径 工程文件路径(mode 5)需要当前地图已打开并保存才能获取。在实际使用中需要检查返回值: ```python # 获取工程文件所在目录 project_dir = SSProcess.getSysPathName(5) if not project_dir: print("警告: 当前没有打开的工程或工程未保存") print("无法使用相对路径保存输出文件") else: print(f"工程目录: {project_dir}") # 在工程目录下创建输出文件 output_dir = project_dir + "output/" output_file = output_dir + "result.json" print(f"输出文件将保存到: {output_file}") ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L99-L103) ### 跨平台系统目录访问 系统目录(mode 6)会根据操作系统类型自动选择正确的路径: ```python import os # 获取系统目录(跨平台兼容) system_dir = SSProcess.getSysPathName(6) if os.name == "nt": print(f"Windows 系统目录: {system_dir}") # 示例:访问 Windows 字体目录 font_dir = system_dir + "\\Fonts\\" else: print(f"Unix/Linux 系统目录: {system_dir}") # 示例:访问系统共享目录 font_dir = system_dir + "/share/fonts/" ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L104-L111) ### 工作台面目录操作 工作台面目录(mode 7/8)允许访问用户特定的配置和资源: ```python # 获取工作台面目录 workspace_dir = SSProcess.getSysPathName(7) print(f"当前工作台面目录: {workspace_dir}") # 工作台面目录的典型子目录 scripts_dir = workspace_dir + "scripts/" templates_dir = workspace_dir + "templates/" config_dir = workspace_dir + "config/" print(f"工作台面脚本目录: {scripts_dir}") print(f"工作台面模板目录: {templates_dir}") print(f"工作台面配置目录: {config_dir}") ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L112-L113) ## 路径获取流程 `getSysPathName` 方法的执行逻辑如下: ```mermaid flowchart TD A[调用 getSysPathName] --> B{判断 mode 参数} B -->|mode 0| C[调用 global_options.getConfigurePath] C --> C1[添加斜杠并返回] B -->|mode 1| D[调用 global_options.getTemplatePath] D --> D1[添加斜杠并返回] B -->|mode 2| E[调用 global_options.getCommonPath] E --> E1[添加斜杠并返回] B -->|mode 3| F[调用 global_options.getSchemeFilePath] F --> F1[参数为 scripts] F1 --> F2[添加斜杠并返回] B -->|mode 4| G[调用 global_options.getEpsTempPath] G --> G1[添加斜杠并返回] B -->|mode 5| H[获取当前地图项目名] H --> H1{项目名有效?} H1 -->|否| H2[返回空字符串] H1 -->|是| H3[使用 Path.parent 提取父目录] H3 --> H4[返回目录路径] B -->|mode 6| I{判断操作系统} I -->|Windows| J[获取 WINDIR 环境变量] I -->|Unix| K[返回 /usr] J --> L[转换为 Path 对象] K --> L L --> L1[返回路径字符串] B -->|mode 7/8| M[调用 global_options.getSchemeFilePath] M --> M1[参数为空字符串] M1 --> M2[添加斜杠并返回] B -->|其他| N[返回空字符串] style A fill:#e1f5ff style H fill:#fff4e1 style I fill:#fff4e1 ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L85-L116) ## 综合应用示例 以下是一个综合示例,展示如何在实际脚本中系统性地使用各种路径功能: ```python from sunvpy import SSProcess from pathlib import Path import json def setup_script_environment(): """设置脚本运行环境并输出路径信息""" print("=" * 70) print("SunvStation 系统路径信息") print("=" * 70) # 获取各类系统路径 paths = { "配置路径": SSProcess.getSysPathName(0), "模板路径": SSProcess.getSysPathName(1), "公共资源路径": SSProcess.getSysPathName(2), "脚本路径": SSProcess.getSysPathName(3), "临时文件路径": SSProcess.getSysPathName(4), "工程文件路径": SSProcess.getSysPathName(5), "系统目录": SSProcess.getSysPathName(6), "工作台面目录": SSProcess.getSysPathName(7) } # 输出路径信息 for name, path in paths.items(): if path: print(f"✓ {name:15s}: {path}") else: print(f"✗ {name:15s}: (未设置或不可用)") print("=" * 70) # 检查关键路径的可用性 if not paths["工程文件路径"]: print("\n警告: 当前没有打开的工程") print("某些功能可能无法正常工作") # 返回路径字典供后续使用 return paths def create_output_file(filename): """在合适的位置创建输出文件""" # 优先使用工程目录 project_dir = SSProcess.getSysPathName(5) if project_dir: output_dir = Path(project_dir) / "output" else: # 降级使用临时目录 temp_dir = SSProcess.getSysPathName(4) output_dir = Path(temp_dir) # 创建输出目录 output_dir.mkdir(parents=True, exist_ok=True) # 构造完整文件路径 output_file = output_dir / filename return str(output_file) def load_custom_config(config_name): """从工作台面目录加载自定义配置""" workspace_dir = SSProcess.getSysPathName(7) if not workspace_dir: print("错误: 无法获取工作台面目录") return None config_dir = Path(workspace_dir) / "config" config_file = config_dir / config_name if not config_file.exists(): print(f"警告: 配置文件不存在: {config_file}") return None try: with open(config_file, 'r', encoding='utf-8') as f: config = json.load(f) print(f"成功加载配置: {config_file}") return config except Exception as e: print(f"加载配置失败: {e}") return None # 主程序 if __name__ == "__main__": # 设置环境并获取路径信息 paths = setup_script_environment() # 创建输出文件 output_file = create_output_file("script_output.json") print(f"\n输出文件将保存到: {output_file}") # 加载自定义配置 custom_config = load_custom_config("my_config.json") if custom_config: print(f"自定义配置: {custom_config}") ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L71-L116), [PySSProcess.py](PySSProcess.py#L53-L86) ## 最佳实践 在使用系统路径管理功能时,遵循以下最佳实践可以提高脚本的健壮性和可移植性: ### 1. 优先使用系统路径而非硬编码 ```python # 好的做法:使用系统路径 template_path = SSProcess.getSysPathName(1) template_file = template_path + "standard.egdb" # 不好的做法:硬编码路径 template_file = "C:\\Program Files\\SunvStation\\templates\\standard.egdb" ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L71-L116) ### 2. 始终检查路径有效性 ```python project_dir = SSProcess.getSysPathName(5) if not project_dir: print("警告: 工程目录不可用,使用临时目录") output_dir = SSProcess.getSysPathName(4) else: output_dir = project_dir ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L99-L103) ### 3. 使用 pathlib 进行路径操作 ```python from pathlib import Path # 推荐做法:使用 pathlib script_path = SSProcess.getSysPathName(3) script_file = Path(script_path) / "utils.py" # 可以方便地检查文件是否存在 if script_file.exists(): print(f"脚本文件存在: {script_file}") ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L103-L103) ### 4. 临时文件及时清理 ```python import os # 在临时目录创建临时文件 temp_dir = SSProcess.getSysPathName(4) temp_file = temp_dir + "temp_data.tmp" # 使用后及时清理 try: # 处理临时文件... pass finally: if os.path.exists(temp_file): os.remove(temp_file) print(f"已删除临时文件: {temp_file}") ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L97-L98) ### 5. 处理路径中的斜杠 `getSysPathName` 返回的路径都以斜杠结尾(`/`),这简化了路径拼接操作: ```python config_path = SSProcess.getSysPathName(0) # config_path 已包含结尾斜杠,无需额外添加 config_file = config_path + "system.xml" # 正确拼接 ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L90-L98) ## 错误处理与调试 在使用系统路径功能时可能会遇到各种错误情况,以下是一些常见的错误处理模式: ### 常见错误类型 | 错误类型 | 可能原因 | 处理方法 | |---------|---------|---------| | 返回空字符串 | 路径不可用或未配置 | 检查返回值,提供降级方案 | | 路径不存在 | 目录被删除或未创建 | 使用 `os.makedirs()` 创建目录 | | 权限错误 | 无访问权限 | 使用 try-except 捕获异常 | | 跨平台路径问题 | 使用了平台特定的路径分隔符 | 使用 `os.path.join()` 或 `pathlib.Path` | ### 错误处理示例 ```python import os from pathlib import Path def safe_get_path(mode): """安全地获取路径并进行验证""" # 获取路径 path = SSProcess.getSysPathName(mode) # 检查路径是否有效 if not path: raise ValueError(f"模式 {mode} 对应的路径不可用") # 转换为 Path 对象 path_obj = Path(path) # 检查路径是否存在(对于需要创建的路径可跳过此检查) if not path_obj.exists(): print(f"警告: 路径不存在 - {path}") print("尝试创建路径...") try: path_obj.mkdir(parents=True, exist_ok=True) print(f"成功创建路径: {path}") except PermissionError: raise PermissionError(f"无权限创建路径: {path}") except Exception as e: raise RuntimeError(f"创建路径失败: {e}") # 检查是否为目录 if not path_obj.is_dir(): raise RuntimeError(f"路径不是目录: {path}") return str(path_obj) # 使用示例 try: config_dir = safe_get_path(0) print(f"配置目录: {config_dir}") except Exception as e: print(f"获取配置目录失败: {e}") print("使用默认配置目录...") config_dir = "./default_config/" ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L71-L116) ## API 快速参考 以下是系统路径管理相关方法的快速参考表: | 方法 | 参数 | 返回值 | 说明 | |-----|------|--------|------| | `getSysPathName(mode)` | mode: int (0-8) | str | 获取指定模式的系统路径 | **GlobalOptions 底层方法**(供高级用户参考): | 方法 | 返回值 | 说明 | |-----|--------|------| | `getConfigurePath()` | std::filesystem::path | 获取配置路径 | | `getTemplatePath()` | std::filesystem::path | 获取模板路径 | | `getCommonPath()` | std::filesystem::path | 获取公共资源路径 | | `getEpsTempPath()` | std::filesystem::path | 获取临时文件路径 | | `getSchemeFilePath(fileName)` | std::filesystem::path | 获取工作台面下的文件路径 | | `getScriptsPath()` | std::filesystem::path | 获取当前台面下的 scripts 文件夹路径 | Sources: [PySSWidget.py](PySSWidget.py#L989-L1390), [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L71-L116) ## 下一步学习 掌握了系统路径管理的方法后,您可以继续学习以下相关主题: - **获取工作空间信息**:[获取工作空间信息](34-huo-qu-gong-zuo-kong-jian-xin-xi) 了解如何获取工作空间、地图、图层等系统信息 - **地图缩放控制**:[地图缩放控制](36-di-tu-suo-fang-kong-zhi) 学习如何控制地图视图的缩放和平移 - **数据交换与导入导出**:[数据交换参数配置](26-shu-ju-jiao-huan-can-shu-pei-zhi) 探索如何配置和管理数据交换流程 - **工作空间与地图概念**:[工作空间与地图概念](8-gong-zuo-kong-jian-yu-di-tu-gai-nian) 深入理解工作空间和地图的底层架构 通过系统学习这些内容,您将能够构建功能完善、路径规范的 SunvStation 二次开发脚本,充分发挥系统的强大功能。