From a03798418f0da5623cb5bcd499d5969585dfb50f Mon Sep 17 00:00:00 2001 From: duxin Date: Tue, 7 Jul 2026 10:38:16 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A2=9E=E5=BC=BA=20PROJ/GDAL=20?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E6=A3=80=E6=B5=8B=20=E2=80=94=20=E5=A4=9A?= =?UTF-8?q?=E7=BA=A7=E5=9B=9E=E9=80=80=E6=90=9C=E7=B4=A2=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: sys.prefix 指向 test_env,该环境不含 GDAL/PROJ 数据文件, 导致 _find_and_set_gdal_env() 找不到 proj.db。 修复: 按优先级扩展搜索路径: 1. CONDA_PREFIX 环境变量(当前激活的 Conda 环境) 2. sys.prefix(Python 安装前缀) 3. CONDA_ROOT / MAMBA_ROOT_PREFIX 4. 从 PATH 推断 conda 安装根目录 5. 硬编码回退(WQ_GUI 路径 + 常见目录 ProgramData) 每个前缀尝试 Windows (Library/share/...) 和 Linux (share/...) 子目录。 找不到时打印已搜索前缀数量供用户诊断。 --- src/gui/water_quality_gui_v2.py | 103 +++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 22 deletions(-) diff --git a/src/gui/water_quality_gui_v2.py b/src/gui/water_quality_gui_v2.py index 3c6f7a9..637e7b1 100644 --- a/src/gui/water_quality_gui_v2.py +++ b/src/gui/water_quality_gui_v2.py @@ -25,33 +25,90 @@ import sys # ═══════════════════════════════════════════════════════════════ def _find_and_set_gdal_env(): - """根据 sys.prefix 自动推断并强设 PROJ_LIB 和 GDAL_DATA 环境变量""" - # sys.prefix 在 Conda 环境下通常为: - # D:\...\anconda\envs\WQ_GUI - # PROJ 和 GDAL 的数据文件位于: - # {sys.prefix}\Library\share\proj (含 proj.db) - # {sys.prefix}\Library\share\gdal - prefix = sys.prefix - candidates_proj = [ - os.path.join(prefix, "Library", "share", "proj"), # Windows Conda - os.path.join(prefix, "share", "proj"), # Linux/Mac Conda - ] - candidates_gdal = [ - os.path.join(prefix, "Library", "share", "gdal"), - os.path.join(prefix, "share", "gdal"), - ] + """动态推断并强设 PROJ_LIB 和 GDAL_DATA 环境变量 - proj_lib = None - for path in candidates_proj: + 按优先级搜索 proj.db 和 GDAL data 目录: + 1. CONDA_PREFIX 环境变量(当前激活的 Conda 环境) + 2. sys.prefix(Python 安装前缀) + 3. CONDA_ROOT / CONDA_BASE(base 环境) + 4. 常见 Conda 安装目录 + 5. 硬编码回退路径(WQ_GUI 环境) + """ + def _check_proj(path): + """检查路径下是否含有效的 proj.db""" proj_db = os.path.join(path, "proj.db") if os.path.isfile(proj_db): - proj_lib = path - break + return path + return None + def _check_gdal(path): + """检查路径下是否含 GDAL 数据文件(以 gdalvrt.xsd 或 pcs.csv 为准)""" + for marker in ("gdalvrt.xsd", "pcs.csv", "gcs.csv"): + if os.path.isfile(os.path.join(path, marker)): + return path + return None + + # --- 构建搜索前缀列表 --- + prefixes = [] + + # 1) CONDA_PREFIX(当前激活环境,最优先) + conda_prefix = os.environ.get("CONDA_PREFIX", "") + if conda_prefix: + prefixes.append(conda_prefix) + + # 2) sys.prefix(Python 运行环境) + if sys.prefix and sys.prefix not in prefixes: + prefixes.append(sys.prefix) + + # 3) CONDA_ROOT / 其他 conda 线索 + for key in ("CONDA_ROOT", "MAMBA_ROOT_PREFIX"): + val = os.environ.get(key, "") + if val and val not in prefixes: + prefixes.append(val) + + # 4) 从 PATH 推断 conda 安装根目录 + for path_dir in os.environ.get("PATH", "").split(os.pathsep): + lower = path_dir.lower() + if "anaconda" in lower or "miniconda" in lower or "anconda" in lower: + # 提取 conda 根目录: .../anconda/ 或 .../anconda/envs/xxx + if os.path.basename(path_dir).lower() == "condabin": + root = os.path.dirname(path_dir) + elif lower.endswith("scripts") or lower.endswith("bin"): + root = os.path.dirname(path_dir) + else: + root = path_dir + if root and root not in prefixes: + prefixes.append(root) + + # 5) 硬编码回退(用户已知的 WQ_GUI 路径 + 常见目录) + hardcoded = [ + r"D:\111\changyongruanjian\anconda\envs\WQ_GUI", + r"D:\111\changyongruanjian\anconda", + r"C:\ProgramData\anaconda3", + r"C:\ProgramData\miniconda3", + ] + for p in hardcoded: + if os.path.isdir(p) and p not in prefixes: + prefixes.append(p) + + # --- 对每个前缀尝试 Windows + Linux 子目录 --- + proj_lib = None gdal_data = None - for path in candidates_gdal: - if os.path.isdir(path): - gdal_data = path + + for prefix in prefixes: + if not proj_lib: + for sub in ("Library/share/proj", "share/proj", "Library\\share\\proj", "share\\proj"): + path = os.path.join(prefix, sub) + proj_lib = _check_proj(path) + if proj_lib: + break + if not gdal_data: + for sub in ("Library/share/gdal", "share/gdal", "Library\\share\\gdal", "share\\gdal"): + path = os.path.join(prefix, sub) + gdal_data = _check_gdal(path) + if gdal_data: + break + if proj_lib and gdal_data: break if proj_lib: @@ -59,12 +116,14 @@ def _find_and_set_gdal_env(): print(f"[ENV] PROJ_LIB → {proj_lib}") else: print("[ENV] ⚠ 未找到 proj.db,PROJ_LIB 保持系统默认,可能影响坐标转换") + print(f"[ENV] (已搜索 {len(prefixes)} 个前缀: {prefixes[:3]}...)") if gdal_data: os.environ["GDAL_DATA"] = gdal_data print(f"[ENV] GDAL_DATA → {gdal_data}") else: print("[ENV] ⚠ 未找到 GDAL data 目录,GDAL_DATA 保持系统默认") + print(f"[ENV] (已搜索 {len(prefixes)} 个前缀: {prefixes[:3]}...)") _find_and_set_gdal_env()