Save Python console output to Java variable - java

I have problem with saving python script's output to java variable. My code looks like...
Python script:
def main(argv):
filepath = argv[1]
...
output = results.get_forecast(14).predicted_mean.to_json()
print(output)
if __name__ == "__main__":
main(sys.argv)
And it works - results are printed to console - everything's fine.
My Java code:
ProcessBuilder pb = new ProcessBuilder("python", "-u",
"path/to/script.py", args_filepath).inheritIO();
try {
Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder predictionString = new StringBuilder();
String line;
while((line = br.readLine()) != null) {
predictionString.append(line);
}
int exitCode = p.waitFor();
System.out.println("VALUE: " + predictionString.toString());
br.close();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
That part also works... I mean it works in a way that it executes the python's code, writes output to console, but it doesn't save the output string to the predictionString.

Use redirectErrorStream method to capturing output stream.
ProcessBuilder pb = new ProcessBuilder("python", "-u",
"path/to/script.py", args_filepath)
.redirectErrorStream(true);
instead of
ProcessBuilder pb = new ProcessBuilder("python", "-u",
"path/to/script.py", args_filepath).inheritIO();

Related

How to return value from Python script to Java using ProcessBuilder?

I am trying to get return value from python script into Java using ProcessBuilder. I am expecting the value "This is what I am looking for" in Java. Can anyone point me as to what is wrong in below logic?
I am using python3 and looking to have this done using java standard libraries.
test.py code
import sys
def main33():
return "This is what I am looking for"
if __name__ == '__main__':
globals()[sys.argv[1]]()
Java code
String filePath = "D:\\test\\test.py";
ProcessBuilder pb = new ProcessBuilder().inheritIO().command("python", "-u", filePath, "main33");
Process p = pb.start();
int exitCode = p.waitFor();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
line = in.readLine();
while ((line = in.readLine()) != null){
line = line + line;
}
System.out.println("Process exit value:"+exitCode);
System.out.println("value is : "+line);
in.close();
output
Process exit value:0
value is : null
When you spawn a process from another process, they can only (mostly rather) communicate through their input and output streams. Thus you cannot expect the return value from main33() in python to reach Java, it will end its life within Python runtime environment only. In case you need to send something back to Java process you need to write that to print().
Modified both of your python and java code snippets.
import sys
def main33():
print("This is what I am looking for")
if __name__ == '__main__':
globals()[sys.argv[1]]()
#should be 0 for successful exit
#however just to demostrate that this value will reach Java in exit code
sys.exit(220)
public static void main(String[] args) throws Exception {
String filePath = "D:\\test\\test.py";
ProcessBuilder pb = new ProcessBuilder()
.command("python", "-u", filePath, "main33");
Process p = pb.start();
BufferedReader in = new BufferedReader(
new InputStreamReader(p.getInputStream()));
StringBuilder buffer = new StringBuilder();
String line = null;
while ((line = in.readLine()) != null){
buffer.append(line);
}
int exitCode = p.waitFor();
System.out.println("Value is: "+buffer.toString());
System.out.println("Process exit value:"+exitCode);
in.close();
}
You're overusing the variable line. It can't be both the current line of output and all the lines seen so far. Add a second variable to keep track of the accumulated output.
String line;
StringBuilder output = new StringBuilder();
while ((line = in.readLine()) != null) {
output.append(line);
.append('\n');
}
System.out.println("value is : " + output);

Python on Jar - Running python Script after process end in Java

I want to run a python script(tensorflow's Image label script) after RPi's camera module captures a photo using a jar file. I have tried both Runtime and ProcessBuilder, but it says no file or Directory found.
Here's my Code for the Runtime Code:
Process rt = Runtime.getRuntime().exec("python3 -m scripts.image-label.py");
rt.waitFor();
BufferedReader in = new BufferedReader(new InputStreamReader(rt.getInputStream()));
String read = in.readLine();
ML = read;
result resfin = new result();
resfin.setVisible(true);
And here's the code for my ProcessBuilder one:
ProcessBuilder builder = new ProcessBuilder("/home/pi/Desktop/ML/scripts/image-label.py");
Process np = builder.start();
np.waitFor();
BufferedReader in = new BufferedReader(new InputStreamReader(np.getInputStream()));
String read = in.readLine();
ML = read;
result resfin = new result();
resfin.setVisible(true);
Am i doing something wrong? Or am i missing something? Any help would be appreciated!
I have tried with the following code, it is working fine, though I have not tried with -m "module" flag, since I do not know how to create a module file in python.
Found some of the issues with code:
1. You need to pass python3 as an argument to process builder as shown below
2. Provide an absolute path for a python file.
3. You can use either of Runtime or ProcessBuilder without an issue.
// Process rt = Runtime.getRuntime().exec("python3 -m /Users/<user-name>/demo/JavaNotepad/src/main/java/com/mypython.py");
ProcessBuilder builder = new ProcessBuilder("python3", "-m", "/Users/<user-name>/demo/JavaNotepad/src/main/java/com/mypython.py");
Process rt = builder.start();
int exitCode = rt.waitFor();
System.out.println("Process exited with : " + exitCode);
BufferedReader in = new BufferedReader(new InputStreamReader(rt.getInputStream()));
BufferedReader err = new BufferedReader(new InputStreamReader(rt.getErrorStream()));
System.out.println("Python file output:");
String line;
BufferedReader reader;
if (exitCode != 0) {
reader = err;
} else {
reader = in;
}
while ((line = reader.readLine()) != null) {
System.out.println(line);
}

Failed to execute child process “'scriptName.sh” (No such file or directory)

String command= "/usr/bin/gnome-terminal.wrapper -e 'startDemonstrator.sh; bash'";
File workDir = new File("/home/malju/Desktop");
Process pr = Runtime.getRuntime().exec(command, null, workDir);
After I execute this line of code I get the error above. My script is located in the Desktop folder. I already tried adding ./startDemonstrator and full path. I always get the error above. What can be the reason be?
I am just trying to open a sh script after the terminal is opened.
First try like below:-
String command= "/home/malju/Desktop/startDemonstrator.sh";
Process pr = Runtime.getRuntime().exec(command);
p.waitFor();
If still not working try with below approach with ProcessBuilder.
String result = "";
String[] command = {"/home/malju/Desktop/startDemonstrator.sh"};
ProcessBuilder process = new ProcessBuilder(command);
Process p ;
try {
p = process.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
StringBuilder builder = new StringBuilder();
String line = null;
while ( (line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
result = builder.toString();
}
catch (IOException e)
{ System.out.print("error");
e.printStackTrace();
}

Open ffplay & execute command with ProcessBuilder not working

I was tried to use ProcessBuilder for open ffplay.exe and execute command into ffplay. However it is unsuccessful. How could I do that?
Code:
ProcessBuilder pb = new ProcessBuilder();
pb.command("C:\\Windows\\System32\\cmd.exe", "/c",
"C:\\ffmpeg\\bin\\ffplay.exe", "tcp://192.168.1.1:5555");
pb.start();
Try using Runtime.getRuntime().exec() and doing like this :-
String[] command = {"ffplay.exe", "tcp://192.168.1.1:5555"}; // add in String array in sequence, the commands to execute
Process process = Runtime.getRuntime().exec(String[] options, null, new File("C:\\ffmpeg\\bin"));
int returnVal = process.waitFor(); // should return 0 for correct execution
try {
final BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line); //check for the inputstream & see the output here
}
reader.close();
} catch (final Exception e) {
e.printStackTrace();
}

Collect Linux command output

I am now on a linux machine. I have a Java program which would run some linux command, for example ps, top, list or free -m.
The way to run a command in Java is as follows:
Process p = Runtime.getRuntime().exec("free -m");
How could I collect the output by Java program? I need to process the data in the output.
Use Process.getInputStream() to get an InputStream that represents the stdout of the newly created process.
Note that starting/running external processes from Java can be very tricky and has quite a few pitfalls.
They are described in this excellent article, which also describes ways around them.
To collect the output you could do something like
Process p = Runtime.getRuntime().exec("my terminal command");
p.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line = "";
String output = "";
while ((line = buf.readLine()) != null) {
output += line + "\n";
}
System.out.println(output);
This would run your script and then collect the output from the script into a variable. The link in Joachim Sauer's answer has additional examples of doing this.
As for some command need to wait for a while, add p.waitFor(); if necessary.
public static void main(String[] args) {
CommandLineHelper obj = new CommandLineHelper();
String domainName = "google.com";
//in mac oxs
String command = "ping -c 3 " + domainName;
String output = obj.executeCommand(command);
System.out.println(output);
}
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
The technicalities of calling an external process are quite involved. The jproc library helps abstracting over these by automatically consuming the output of the command and providing the result as a string. The example above would be written like this:
String result = ProcBuilder.run("free", "-m");
It also allows to set a timeout, so that your application isn't blocked by an external command that is not terminating.
public String RunLinuxGrepCommand(String command) {
String line = null;
String strstatus = "";
try {
String[] cmd = { "/bin/sh", "-c", command };
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = in.readLine()) != null) {
strstatus = line;
}
in.close();
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.flush();
String stackTrace = sw.toString();
int lenoferrorstr = stackTrace.length();
if (lenoferrorstr > 500) {
strstatus = "Error:" + stackTrace.substring(0, 500);
} else {
strstatus = "Error:" + stackTrace.substring(0, lenoferrorstr - 1);
}
}
return strstatus;
}
This functioin will give result of any linux command

Categories