Runtime.getRuntime().exec 找不到默认的 python 版本

Runtime.getRuntime().exec does not find the default python version

我想使用 Runtime.getRuntime().exec 来执行一个简单的 python 脚本 Runtime.getRuntime().exec("python test.py"),它只包含很少的导入,但失败并出现错误 1。我跟踪错误,发现发现某些库未找到:

Traceback (most recent call last):
File "/Users/firetiti/NetBeans/FiReTiTiLiB/Test.py", line 6, in <module>
from PIL import Image
ImportError: No module named PIL

当我在终端中执行相同的脚本时,一切正常。所以我将 python 替换为 python Runtime.getRuntime().exec("/somewhere/in/my/computer/python3.6 test.py") 的绝对路径,它起作用了。

看来Runtime.getRuntime().exec并没有使用python配置的版本。我该如何解决?

如果您在 Java 中 运行 exec("python test.py"),将尝试以与任何其他应用程序相同的方式将 python 解析为可执行文件。

假设你使用的是UNIX,Linux或者MacOSX,顺序大致如下:

  1. JVM 执行 fork 系统调用来创建子进程。子进程继承父(JVM)进程的环境变量。

  2. 子进程执行 exec 系统调用,将命令名称、参数和环境变量传递给它。

  3. 如果命令名称是一个简单名称,系统调用会尝试通过在命令搜索路径上的目录中搜索可执行文件来将名称解析为路径名;即具有适当的执行权限集的人。

  4. 如果找到可执行文件,则根据其签名将其加载到子进程或解释为脚本。

在您的情况下,第 3 步不起作用。具体来说,它在搜索路径上找到了错误版本的 python。搜索路径由 PATH 环境变量确定...从父 JVM 继承。

因此,如果您在交互式 shell 和 Java 中得到不同的结果,那很可能意味着它们具有不同的 PATH 变量。这是要检查的第一件事。例如,在您的 Java 应用程序中,查看以下输出:

  System.out.println(System.environ().get("PATH"));

并检查它找到的第一个 python 命令是否是您想要的版本。

可能的解决方案:

  • 在启动 JVM 之前适当地设置 PATH
  • 使用ProcessBuilder在修改后的环境下执行外部命令
  • python 命令使用绝对路径名。
  • 如果这是 Python 2 vs 3,请将命令名称命名为 python2python3。 (典型的 Linux 包等将从 python2python3 link 到正确的可执行文件。)