I wanted to use Runtime.getRuntime().exec
to execute a simple python script Runtime.getRuntime().exec("python test.py")
which contains only few imports, but it failed with error 1. I traced the error, and I found out that some libraries were not found:
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
When I executed the same script into a terminal, everything was fine. So I replaced python
with the absolute path to python Runtime.getRuntime().exec("/somewhere/in/my/computer/python3.6 test.py")
, and it worked.
So it seems that Runtime.getRuntime().exec
does not use the configured version of python. How can I fix it?
If you run exec("python test.py")
in Java, will try to resolve python
to an executable file in the same way as any other application does.
Assuming that you are using UNIX, Linux or Mac OSX, the sequence is roughly as follows:
The JVM performs a
fork
syscall to create a child process. The child process inherits the environment variables of the parent (JVM) process.The child process performs an exec syscall, passing it the command name, arguments and environment variables.
If the command name is a simple name, the syscall attempts to resolving the name to a pathname by searching the directories on the command search path for an executable file; i.e. one with the appropriate execute permission set.
If an executable is found, it is either loaded into the child process or interpreted as a script, depending on its signature.
In your case, it is step 3 that is not working. Specifically, it finds the wrong version of python
on the search path. The search path is determined by the PATH
environment variable ... as inherited from the parent JVM.
So, if you get different results in an interactive shell and from Java, that most likely means that they have different PATH
variables. That is the first thing to check. For example, in your Java application, see what this outputs:
System.out.println(System.environ().get("PATH"));
and check that the first python
command it would find is the version that you want.
Possible solutions:
- Set
PATH
appropriately before starting the JVM - Use
ProcessBuilder
to execute the external command with a modified environment - Use an absolute pathname for the
python
command. - If this is Python 2 vs 3, give the command name as
python2
orpython3
. (A typical Linux package etc will link frompython2
andpython3
to the correct executables.)