fix: 增强 PROJ/GDAL 环境检测 — 多级回退搜索策略

问题: 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/...) 子目录。
找不到时打印已搜索前缀数量供用户诊断。
This commit is contained in:
duxin
2026-07-07 10:38:16 +08:00
parent 2b5c77131e
commit a03798418f

View File

@ -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.prefixPython 安装前缀)
3. CONDA_ROOT / CONDA_BASEbase 环境)
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.prefixPython 运行环境)
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.dbPROJ_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()