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

FiReTiTi :

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().execdoes not use the configured version of python. How can I fix it?

Stephen C :

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:

  1. The JVM performs a fork syscall to create a child process. The child process inherits the environment variables of the parent (JVM) process.

  2. The child process performs an exec syscall, passing it the command name, arguments and environment variables.

  3. 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.

  4. 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 or python3. (A typical Linux package etc will link from python2 and python3 to the correct executables.)

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=384872&siteId=1