From 6b6e593fa5966b99005877373846f9e235f93053 Mon Sep 17 00:00:00 2001 From: duxin Date: Tue, 7 Jul 2026 16:47:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20pip=20wheel=20GDAL?= =?UTF-8?q?=20=E7=9A=84=20proj.db=20=E6=9C=AA=E8=A2=AB=E6=89=BE=E5=88=B0?= =?UTF-8?q?=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: pip 安装的 GDAL ≥3.5 把 proj.db 放在 {site-packages}/osgeo/data/proj/proj.db 而之前的代码将其加入 prefixes 列表后,搜索循环只查找 {prefix}/Library/share/proj/ 子目录, 导致 site-packages 中的 v6+ proj.db 被漏掉。 修复: 1. 新增独立搜索步骤:直接扫描 site-packages 下 osgeo/data/proj/ 和 osgeo/proj_data/ 目录 2. 找到 v6+ 版本后直接设为 proj_lib, 不再经过前缀子目录搜索(优先级最高) 3. 同时扫描 site-packages/fiona/proj_data/, 找到旧版时打印明确路径警告, 确认 PROJ_DATA 已覆盖该旧版 4. 仅 site-packages 未找到时回退到前缀搜索 --- src/gui/water_quality_gui_v2.py | 86 +++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 30 deletions(-) diff --git a/src/gui/water_quality_gui_v2.py b/src/gui/water_quality_gui_v2.py index d0b68b4..dae12e7 100644 --- a/src/gui/water_quality_gui_v2.py +++ b/src/gui/water_quality_gui_v2.py @@ -172,39 +172,62 @@ def _find_and_set_gdal_env(): pass prefixes.extend(_extra_prefixes) - # 6) pip wheel GDAL: {site-packages}/osgeo/data/proj/proj.db - # (conda-forge GDAL wheel on Windows 有时把 proj.db 放这里) + # 6) pip wheel GDAL / Fiona: {site-packages}/*/proj.db 直接搜索 + # pip 安装的 GDAL ≥3.5 把 proj.db 放在 site-packages/osgeo/data/proj/ + # Fiona 打包的旧版 proj.db 在 site-packages/fiona/proj_data/ + # 优先使用 GDAL 的 v6+,忽略 Fiona 的 v2 + _site_proj = None # site-packages 中找到的 v6+ proj.db + _site_gdal = None + _fiona_v2_path = None # 记录 Fiona 的旧版供警告 try: import site as _site for _sp in _site.getsitepackages(): - pip_proj = os.path.join(_sp, "osgeo", "data", "proj") - if os.path.isfile(os.path.join(pip_proj, "proj.db")): - pip_gdal = os.path.join(_sp, "osgeo", "data", "gdal") - if _sp not in prefixes: - prefixes.append(_sp) + # GDAL wheel: osgeo/data/proj/proj.db + for _sub in ("osgeo/data/proj", "osgeo\\data\\proj", + "osgeo/proj_data", "osgeo\\proj_data"): + _db = os.path.join(_sp, _sub, "proj.db") + if os.path.isfile(_db): + _ver = _check_proj_db_version(_db) + if _ver >= 6 and not _site_proj: + _site_proj = os.path.join(_sp, _sub) + _gd = os.path.join(_sp, "osgeo", "data", "gdal") + if os.path.isdir(_gd): + _site_gdal = _gd + # Fiona 打包的旧版 → 记录供警告 + for _sub in ("fiona/proj_data", "fiona\\proj_data"): + _fdb = os.path.join(_sp, _sub, "proj.db") + if os.path.isfile(_fdb) and not _fiona_v2_path: + _fiona_v2_path = _fdb except Exception: pass - proj_lib = None - gdal_data = None - for prefix in prefixes: - if not proj_lib: - # 先尝试标准子目录(快速路径) - for sub in ("Library/share/proj", "share/proj", - "Library\\share\\proj", "share\\proj"): - db_path = os.path.join(prefix, sub, "proj.db") - if os.path.isfile(db_path) and _check_proj_db_version(db_path) >= 6: - proj_lib = os.path.join(prefix, sub) - break - # 标准路径未找到 → 递归搜索(仅对 conda 环境前缀) - if not proj_lib and ( - os.path.basename(prefix) not in ("", "share", "bin", "Scripts") - ): - proj_lib = _find_proj_in_prefix(prefix) - if not gdal_data: - gdal_data = _find_gdal_in_prefix(prefix) - if proj_lib and gdal_data: - break + # 直接使用 site-packages 中找到的 v6+ proj.db(优先级最高: + # 它和当前 Python 进程中的 GDAL/PROJ 库版本匹配) + if _site_proj: + proj_lib = _site_proj + gdal_data = _site_gdal if _site_gdal else None + else: + proj_lib = None + gdal_data = None + + # site-packages 没找到 → 回退到前缀搜索 + if not proj_lib: + for prefix in prefixes: + if not proj_lib: + for sub in ("Library/share/proj", "share/proj", + "Library\\share\\proj", "share\\proj"): + db_path = os.path.join(prefix, sub, "proj.db") + if os.path.isfile(db_path) and _check_proj_db_version(db_path) >= 6: + proj_lib = os.path.join(prefix, sub) + break + if not proj_lib and ( + os.path.basename(prefix) not in ("", "share", "bin", "Scripts") + ): + proj_lib = _find_proj_in_prefix(prefix) + if not gdal_data: + gdal_data = _find_gdal_in_prefix(prefix) + if proj_lib and gdal_data: + break # ── 应用环境变量 ── if proj_lib: @@ -232,13 +255,16 @@ def _find_and_set_gdal_env(): # ── 屏蔽 Fiona 内部旧版 PROJ 路径 ── # Fiona wheels 捆绑了古老的 proj.db (VERSION.MINOR=2), # 即使设置了 PROJ_DATA 仍然可能被某些旧版 Fiona 忽略。 - # 以下环境变量作为最后防线强制覆盖。 if proj_lib: - # GDAL ≥3.5 同时检查 PROJ_DATA 和 PROJ_LIB os.environ["PROJ_NETWORK"] = "OFF" # 禁用 PROJ 网络下载(避免意外行为) - # 记录此信息供诊断 if "PROJ_DATA" in os.environ: print("[ENV] 已屏蔽 Fiona 内部旧版 PROJ 数据库,全进程统一使用上述 proj.db") + if _fiona_v2_path: + print(f"[ENV] ⚠ 检测到 Fiona 自带的旧版 proj.db (v2) 位于:") + print(f" {_fiona_v2_path}") + print(f" PROJ_DATA 已指向 v6+ 版本,此旧版将被忽略") + if proj_lib: + print(f" 确认全进程 PROJ 来源: {proj_lib}") _find_and_set_gdal_env()