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

Java Runtime.getRuntime().exec找不到默认的python版本,java,runtime.exec,Java,Runtime.exec,我想使用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

我想使用
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
回溯(最近一次呼叫最后一次):
文件“/Users/firetii/NetBeans/firetilib/Test.py”,第6行,在
从PIL导入图像
ImportError:没有名为PIL的模块
当我在终端上执行相同的脚本时,一切都很好。因此,我用python
Runtime.getRuntime().exec(“/somewhere/in/my/computer/python3.6test.py”)
的绝对路径替换了
python
,它成功了

因此,
Runtime.getRuntime().exec
似乎没有使用配置的python版本。如何修复它?

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

假设您使用的是UNIX、Linux或Mac OSX,顺序大致如下:

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

  • 子进程执行exec系统调用,向其传递命令名、参数和环境变量

  • 如果命令名是一个简单的名称,系统调用将尝试通过在命令搜索路径上搜索可执行文件的目录,将该名称解析为路径名;i、 e.具有适当执行权限集的

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

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

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

      System.out.println(System.environ().get("PATH"));
    
    并检查它将找到的第一个
    python
    命令是否是您想要的版本

    可能的解决办法:

    • 在启动JVM之前,适当地设置路径
    • 使用
      ProcessBuilder
      在修改的环境中执行外部命令
    • python
      命令使用绝对路径名
    • 如果这是Python 2 vs 3,则将命令名命名为
      python2
      python3
      。(典型的Linux包etc将从
      python2
      python3
      链接到正确的可执行文件。)
    如果在Java中运行
    exec(“python test.py”)
    ,将尝试以与任何其他应用程序相同的方式将
    python
    解析为可执行文件

    假设您使用的是UNIX、Linux或Mac OSX,顺序大致如下:

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

  • 子进程执行exec系统调用,向其传递命令名、参数和环境变量

  • 如果命令名是一个简单的名称,系统调用将尝试通过在命令搜索路径上搜索可执行文件的目录,将该名称解析为路径名;i、 e.具有适当执行权限集的

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

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

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

      System.out.println(System.environ().get("PATH"));
    
    并检查它将找到的第一个
    python
    命令是否是您想要的版本

    可能的解决办法:

    • 在启动JVM之前,适当地设置路径
    • 使用
      ProcessBuilder
      在修改的环境中执行外部命令
    • python
      命令使用绝对路径名
    • 如果这是Python 2 vs 3,则将命令名命名为
      python2
      python3
      。(典型的Linux包etc将从
      python2
      python3
      链接到正确的可执行文件。)

    非常感谢您的详尽回答。我使用
    System.getenv(“PATH”)
    来显示变量,确实缺少很多东西,但是当我在终端中运行命令
    echo$PATH
    时,它们就出现了。看来我最好的选择就是我已经用过的那个(你的第三个要点“绝对路径名”)。非常感谢你详尽的回答。我使用
    System.getenv(“PATH”)
    来显示变量,确实缺少很多东西,但是当我在终端中运行命令
    echo$PATH
    时,它们就出现了。因此,我的最佳选择似乎是我已经使用过的(您的第三个要点“绝对路径名”)。