在使用 bat 脚本更新环境后,从 java 调用 GDAL 的可移植二进制文件时模块 osgeo (embd.py) 的导入错误。路径变量

ImportError for module osgeo (embd. py) while invoking portable binaries of GDAL from java, after using a bat script to update env. path variables

编辑 1:忘记提及 python,我使用的是嵌入式 python。


我已经从 GIS Internals 下载了 windows 个 GDAL 二进制文件。 前提:

目录结构:

Parent
 |gnuplot
 |mysoft.exe
 |gdal
 |python-embedded
 |jvm
 |gsl2
 |mybinaries
 |mysoftlaunch.bat

bat文件是GDAL二进制文件提供的,我对文件和放入的目录做了相关修改

@echo off

set SDK_ROOT=%~dp0gdal\
set SDK_ROOT=%SDK_ROOT:\=\%
set GNUPLOT_ROOT=%~dp0gnuplot\
set PYTHON_ROOT=%~dp0python-3.7.3-embed-amd64\
@echo %SDK_ROOT%
@echo %GNUPLOT_ROOT%

goto setenv
if "%1" == "setenv" goto setenv

%comspec% /k "%SDK_ROOT%SDKShell.bat" setenv %1
goto exit

:setenv
@echo Setting environment for using the GDAL and MapServer tools.

if "%2"=="hideoci" goto hideoci

set ocipath=0
set _path="%PATH:;=" "%"
for %%p in (%_path%) do if not "%%~p"=="" if exist %%~p\oci.dll set ocipath=1

if "%ocipath%"=="0" goto hideoci
@echo WARNING: If you encounter problems with missing oci libraries then type:
@echo   SDKShell hideoci
goto setenv2

...
...

:setenv2
@echo at set env 2
SET "PATH=%SDK_ROOT%bin;%SDK_ROOT%bin\gdal\python\osgeo;%SDK_ROOT%bin\proj6\apps;%SDK_ROOT%bin\gdal\apps;%SDK_ROOT%bin\ms\apps;%SDK_ROOT%bin\gdal\csharp;%SDK_ROOT%bin\ms\csharp;%SDK_ROOT%bin\curl;%GNUPLOT_ROOT%bin\;%SDK_ROOT%gsl2\bin\;%PATH%"
SET "GDAL_DATA=%SDK_ROOT%bin\gdal-data"
SET "GDAL_DRIVER_PATH=%SDK_ROOT%bin\gdal\plugins"
SET "PYTHONPATH=%SDK_ROOT%bin\gdal\python\osgeo;%SDK_ROOT%bin\gdal\python;%SDK_ROOT%bin\ms\python;%PYTHON_ROOT%"
SET "PROJ_LIB=%SDK_ROOT%bin\proj6\SHARE"
SET "LD_LIB_PATH=%SDK_ROOT%gsl2\lib"
@echo done setting variables
start "MYSOFT" cmd /c java -jar "%~dp0mysoft.exe%"
@echo started mysoftware
exit
:exit

这里有几件事:

  1. 我已经使用 launch4j 为我的 jar 文件提供了到 jvm 的路径,并使它成为一个 exe,这就是为什么有 mysoft.exe
  2. 我在我的软件中指定了相对路径以访问所需的可执行文件或脚本。
  3. 我使用了 python-embedded 并给出了 python 脚本的相对路径,我会像 gdal_merge.py.
  4. 那样调用它
  5. 我不想在 bat 文件和 运行 软件中直接执行 setx 一次,因为如果用户更改软件目录和 运行 脚本同样,windows 中的路径大小限制将用尽,这将是一场灾难。 (为什么我要从 bat 文件启动软件。)

该脚本应该为所有启动的子进程设置环境变量。

我可以确认 gdal_translate 工作正常。 [我确实指定了它的相对路径,而不是从环境中调用它。]

工作流程

  1. 我在 bat 文件中设置环境变量并启动 java 程序。
  2. 我有一个 Java 程序作为用户界面。 Java 程序调用一些可执行文件或脚本,其中包括 gdal_merge.py.
  3. 我在代码中指定 gdal_merge.py 的完整路径并使用 ProcessBuilder
  4. 调用它

错误:

from osgeo import gdal
ModuleNotFoundError: No module named 'osgeo'.

预期的解决方案: 从 bat 文件设置路径后(到 embedded-python、jvm、gdal{都需要像 gdal_data、gdal_driver、二进制文件的路径等),启动 Java 软件继承那些启动 gdal_merge.py 文件的环境变量。

以下方式:

String path = System.getProperty("user.dir");
ProcessBuilder pb = new ProcessBuilder();
pb.inheritIO();
pb.command(Paths.get(path+"/python-embedded/python.exe").toString(),Paths.get(path+"/gdal/....../python/scripts/gdal_merge.py").toString(),...{other parameters required for gdal_merge.py}); 

PS:
Paths.get(x+"abc/def/").toString() - 我正在使用将 *NIX 样式路径转换为 ​​Windows 样式路径。

根据 Issue28245 Python bugs,这是一个故意的功能。嵌入式 python 与您的系统环境完全隔离。

要包含此嵌入式 python 查找包的路径,您需要编辑 pythonxx._pth 文件。

只需在每一行中添加一个路径即可。不需要变量。您也可以添加相对路径。

._pth 文件示例:

pythonxx.zip # default value
. # default value
..\gdal\bin\gdal\python\
..\gdal\bin\gdal\python\osgeo\
..\gdal\bin\gdal\python\scripts\
..\gdal\bin\ms\python\

这很有魅力。