Call and Receive Output from Python Script in Java

Call and receive output from Python script in Java?

Not sure if I understand your question correctly, but provided that you can call the Python executable from the console and just want to capture its output in Java, you can use the exec() method in the Java Runtime class.

Process p = Runtime.getRuntime().exec("python yourapp.py");

You can read up on how to actually read the output from this resource:
http://www.devdaily.com/java/edu/pj/pj010016
import java.io.*;

public class JavaRunCommand {

public static void main(String args[]) {

String s = null;

try {

// run the Unix "ps -ef" command
// using the Runtime exec method:
Process p = Runtime.getRuntime().exec("ps -ef");

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);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
}

There is also an Apache library (the Apache exec project) that can help you with this. You can read more about it here:

http://www.devdaily.com/java/java-exec-processbuilder-process-1

http://commons.apache.org/exec/

Issues in getting the output when calling a python script from Java

The while loop condition has actually already read a line so you are double reading it for every time in the loop.

while ((s = stdInput.readLine()) != null) {
//s=stdInput.readLine(); <- don't need this
System.out.println(s);
output.append(s);
}

/Nick

Issue in calling Python code from Java (without using jython)

I think you could try your luck with the ProcessBuilder class.

If I read the Oracle documentation correctly, the std inputs and outputs are directed to pipes by default but the ProcessBuilder has an easy method for you to explicitly set output (or input) to a file on your system or something else.

If you want your Python program to use the same output as your Java program (likely stdout and stderr), you can use stg like this:

ProcessBuilder pb = new ProcessBuilder("C:\\Python\\Python36-32\\python.exe", "C:\\test2.py");
pb.redirectOutput(Redirect.INHERIT);
Process p = pb.start();

Run python script through Java with files arguments

Unlike python Java may need some help. Do I guess correctly you are running on Windows?

You invoke the Runtime.exec() method. The method returns a Process instance, and in it's documentation you can read

By default, the created process does not have its own terminal or
console. All its standard I/O (i.e. stdin, stdout, stderr) operations
will be redirected to the parent process, where they can be accessed
via the streams obtained using the methods getOutputStream(),
getInputStream(), and getErrorStream(). The parent process uses these
streams to feed input to and get output from the process. Because some
native platforms only provide limited buffer size for standard input
and output streams, failure to promptly write the input stream or read
the output stream of the process may cause the process to block, or
even deadlock.

So it is likely your process is started by the OS but gets blocked due to I/O restrictions. Get around that by reading the STDOUT and STDERR streams until your process finishes. One good programming model is visible at https://www.baeldung.com/run-shell-command-in-java

Execute python script through Java

I managed to fix the issue by constantly reading the "print" and error outputs of the Python file. Whilst I still don't completely understand how this fixed the issue, my best guess is that with this, the Java code keeps the python script "running" until the script itself is finished doing its thing, instead of just opening the script and instantly moving on.

Here's the code:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Test {

public static void main(String... args) throws Exception {

String[] callAndArgs = {"python3", "YourScript.py"};
Process p = Runtime.getRuntime().exec(callAndArgs);

BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));

String s;
while ((s = stdInput.readLine()) != null) {
//System.out.println(s);
}

while ((s = stdError.readLine()) != null) {
//System.out.println(s);
}

}

}

Another Notable Detail is that this code only seems to work when Compiled and run through the Terminal/Geany. If I run the same thing with IntelliJ it does not work. Once again, I'm not sure why this is but I'm suspecting that IntelliJ compiles and runs in a VM of some sorts.

Get error output from Python script called from Java

See When Runtime.exec() won't for many good tips on creating and handling a process correctly. Then ignore it refers to exec and use a ProcessBuilder to create the process. Also break a String arg into String[] args to account for things like paths containing space characters.

Now to the specifics of the problem at hand, it sounds like it is the output from the error stream that is missing. As you noted, calling proc.getErrorStream() and processing that output should fit the requirement.

Running python script from java and sending input/output

As you may have noticed, this is a problem related to Python.

As described in https://unix.stackexchange.com/questions/182537/write-python-stdout-to-file-immediately,

" when process STDOUT is redirected to something other than a terminal, then the output is buffered into some OS-specific-sized buffer (perhaps 4k or 8k in many cases)."

So, you need to call sys.stdout.flush() after each invoke to print.

Or, as a better option, you can change the default behaviour for the process, using the -u param, to get unbuffered output.



Related Topics



Leave a reply



Submit