专题图修改虚拟环境
This commit is contained in:
@@ -160,6 +160,67 @@ def build_qgis_env(qgis_root: str = None) -> dict:
|
||||
return env
|
||||
|
||||
|
||||
def build_clean_subprocess_env() -> dict:
|
||||
"""
|
||||
为 QGIS Python 3.12 子进程构建干净的环境变量。
|
||||
|
||||
问题背景:
|
||||
主进程运行在 venv Python 3.10 中,继承了 venv 的环境变量
|
||||
(PYTHONPATH 指向 venv site-packages、VIRTUAL_ENV、PATH 含 venv Scripts 等)。
|
||||
QGIS Python 3.12 子进程如果继承这些变量,DLL 加载会被干扰,
|
||||
导致 0xC0000005 (ACCESS_VIOLATION) 崩溃。
|
||||
|
||||
同时,QGIS_PREFIX_PATH、QT_PLUGIN_PATH 等变量也会与
|
||||
QGIS 内置 DLL 加载机制冲突,同样导致崩溃。
|
||||
|
||||
策略:
|
||||
从 os.environ 中移除所有 Python/venv 相关的污染变量,
|
||||
只保留操作系统正常运行所需的基础变量(SystemRoot、TEMP 等)。
|
||||
QGIS Python 3.12 仅通过 sys.path 即可正确加载所有模块和 DLL。
|
||||
"""
|
||||
env = dict(os.environ)
|
||||
|
||||
# 先记录 venv 路径(后续清理 PATH 时需要用)
|
||||
venv_root = env.get("VIRTUAL_ENV", "").lower()
|
||||
|
||||
# 移除 Python/venv 相关变量 —— 这些会污染 QGIS Python 3.12 的 DLL 加载
|
||||
for key in [
|
||||
"PYTHONPATH", # venv 设置,指向 site-packages → DLL 冲突
|
||||
"PYTHONHOME", # 如果存在,改变 Python 查找路径
|
||||
"VIRTUAL_ENV", # venv 标识,不必要
|
||||
"PYTHONDONTWRITEBYTECODE",
|
||||
"QGIS_PREFIX_PATH", # 与 QGIS 内置 DLL 加载冲突
|
||||
"QT_PLUGIN_PATH", # 与 Qt DLL 加载冲突
|
||||
"GDAL_DATA", # build_qgis_env 设置,可能导致路径冲突
|
||||
"PROJ_DATA", # build_qgis_env 设置,可能导致路径冲突
|
||||
]:
|
||||
env.pop(key, None)
|
||||
|
||||
# 清理 PATH:仅移除 venv 相关路径(避免 DLL 搜索顺序冲突)
|
||||
# 保留 QGIS/系统路径(测试证明这些是安全的)
|
||||
if venv_root:
|
||||
path_parts = env.get("PATH", "").split(";")
|
||||
clean_parts = []
|
||||
for p in path_parts:
|
||||
pl = p.lower().strip()
|
||||
if not pl:
|
||||
continue
|
||||
# 跳过 venv 相关路径(.venv/Scripts, .venv/Lib 等)
|
||||
if venv_root in pl:
|
||||
continue
|
||||
clean_parts.append(p)
|
||||
env["PATH"] = ";".join(clean_parts)
|
||||
|
||||
# 移除 VIRTUAL_ENV 本身(已从 PATH 清理中使用过)
|
||||
env.pop("VIRTUAL_ENV", None)
|
||||
|
||||
logger.debug(
|
||||
f"Clean env built: removed PYTHONPATH/VIRTUAL_ENV/venv-PATH, "
|
||||
f"kept {len(env)} vars"
|
||||
)
|
||||
return env
|
||||
|
||||
|
||||
def is_qgis_available(qgis_root: str = None) -> bool:
|
||||
"""检查 QGIS 环境是否可用"""
|
||||
return get_qgis_python_path(qgis_root) is not None
|
||||
|
||||
Reference in New Issue
Block a user