Running python from Java using Process Builder - java

For an existing Java code that I want to extend, I need to run a python code from within Java. I am using Process builder for this:
ProcessBuilder pb = new ProcessBuilder("python", "/directorypath/mypython.py");
Process p=pb.start();
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
}
While the code runs perfectly fine from command line, in Java I get a "We need BeautifulSoup, sorry" error. As far as I understand,this means Java environment is missing some sort of libraries but then the code works perfectly from command line.
Do I need to send some environment variables? If yes, what and how?
I have 'BeautifulSoup4' installed and it is up-to-date.

Not a definitive answer but this looks to me as a problem in the environment which this process runs in; it is probably missing some environment variables which are expected by python to find your "BeautifulSoup4" extension.
A ProcessBuilder has an .environment() method returning a Map<String, String> whose keys are the environment variables and whose values are those variables' values. NOTE THAT MODIFYING THIS MAP ACTUALLY ALTERS THE ENVIRONMENT! (the one of the process you will launch, that is).
Try and print your environment and compare it with what it is when you run from the command line.

Related

Running gnuplot on java

I´m running a java project using gnuplot to generate charts in pdf but I want to save those files in another folder outside my working directory. Is that possible?
I have this for now
Process proc = Runtime.getRuntime().exec("gnuplot test.gp");
BufferedReader reader =
new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
System.out.print(line + "\n");
}
proc.waitFor();
In gnuplot console check help command line options. There is the option -e.
You need to have the following argument for exec() in Java.
"gnuplot -e myOutput='<YourPDF>' test.gp"
where you have to replace <YourPDF> with your path. Since I do not know Java, the Java-people have to tell you how you get this done.
A minimal gnuplot script would for example look like the following:
set term pdfcairo
set output myOutput
plot sin(x) # or whatever
set output

Command executed from terminal, failed from Java using ProcessBuilder

I'm trying to execute a command in my terminal. The problem is, when I execute the command in terminal, it succeed, but when I run the command from java, the command is executed but, I got an error message showing me that some python module is missing.
try{
String[] list = { "python3", "script.py" };
ProcessBuilder pb = new ProcessBuilder(list);
pb.directory(
new File("/home/script"));
System.out.println("" + pb.directory());
Process process = pb.start();
InputStream str = process.getErrorStream();
InputStreamReader isr = new InputStreamReader(str);
BufferedReader br = new BufferedReader(isr);
String line;
System.out.printf("Output of running %s is:", Arrays.toString(args));
while ((line = br.readLine()) != null) {
System.out.println(line);}
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String ret = in.readLine();
System.out.println("value is : "+ret);
process.waitFor();
process.destroy();
}catch (Exception ex) {
ex.printStackTrace();
}
The error message:
/home/script
Output of running [] is:Traceback (most recent call last):
File "scraper.py", line 8, in <module>
from selenium import webdriver
ModuleNotFoundError: No module named 'selenium'
value is : null
PS: When I execute the command directly from terminal, everything works good, I don't get the missing module error.
Similar to Java, python allows to import other stuff. That message tells you that your python script wants to use the module selenium, but can't find it.
Most likely you have some special ENV var setup when running commands manually in a shell/console. So check your .bashrc or .initrc or whatever defines your ENV variables. On a unix system, typing the command env might show you all settings, too. Simply check if the env var PYTHONPATH is setup.
As that call works from the command line, then for sure, the module is installed on your system. Your only problem is that python can't find it when you invoke that script through the Java ProcessBuilder!
One solution might be that you "manually" adjust the PYTHONPATH from within your script. Thus: figure the correct setup for PYTHONPATH, then update your script to "do the right thing".
For further details, see the python documentation!

Calling Python process (which executes tycat-terminology image display utility) from Java DOES NOT WORK

I want basically to display images into the console terminal, from a Java main program class. The images should show only in the main terminal console, AND NOT open new image display utility windows (i.e. imagemagick, eog, etc.)
I have tried the following workaround: The following Python code (display_image.py) starts tycat/terminology image display utility that successfully shows an image in the console terminal:
import os
os.system("tycat -g 100x100 /home/user/Dekstop/image.png")
So when I execute that Python snippet everything fine. But, when I process call it from Java, like this way here:
Process proc = Runtime.getRuntime().exec(new String[]{"python","/home/user/Desktop/display_image.py"});
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
System.out.println("Here is the standard error of the command (if any):\n");
String s1 = null;
while ((s1 = stdError.readLine()) != null) {
System.out.println(s1);
}
The process seems hanged and does not show anything. Note, that I run the java class from terminology, still the same issue.
I would appreciate any hint or help that would either solve this problem, OR help me show any image file from Java class inside the terminal console application.
Thanks

Using ProcessBuilder to find version of Java

I am trying to use Java to find out the versions of Java installed on a machine. I have:
List<String> commands = new ArrayList<String>();
commands.add("java.exe");
commands.add("-version");
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("C:\\Program Files\\Java\\jdk1.6.0_45\\bin"));
Process p = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
However, when this is run, the while loop is never executed as the stdInput is empty. If I take out the commands.add("-version"), it will get the input that is output when running "java.exe" command on command line, so it seems adding the -version arguement is causing issues and this also indicates that the directory and java.exe commands are correct. Any help would be appreciated.
The output of java -version is sent to the error stream - reading from that stream should result in the proper output:
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getErrorStream()));
Alternatively, you can call redirectErrorStream(true) to merge the Input and Error streams. If you just wish to just print to the command line, you can use inheritIO on the ProcessBuilder.
The currently running java version can be found without the need for a ProcessBuilder by retrieving the appropriate System property
System.out.println(System.getProperty("java.version"));
java -version prints to stderr. Try using:
ProcessBuilder pb = new ProcessBuilder(commands).redirectErrorStream(true);
That will put stderr in the same stream as stdout and the rest of your code can look as it does now.

Java ProcessBuilder: capture output from scripts run from scripts run from Java

Using Java's ProcessBuilder, I can run an external script, and redirect its output into my GUI.
Process proc = pb.start();
BufferedReader bri = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while (proc.isAlive())
{
// bri may be empty or incomplete.
while ((line = bri.readLine()) != null)
{
textArea.appendText(line);
}
}
Now, the script I am running also calls other scripts and processes. Two of these, that should be captured, are currently displayed in their own xterm windows. Is it possible to also capture these outputs, and display in a similar manner?.
If these outputs are being managed by your source script, I think it will work. Just as an advice, take a look in this article: When Runtime.exec() won't
It is extremammly important to read it to learn how to work with external processes correctly.

Categories

Resources