Reputation: 560
I had to execute a java file(passing a single argument) from Python and after execution, return the result back to the script that called it. I wrote a little java test program that takes an argument and prints out some stuff to the stdout. Here is the java program
import java.util.*;
class TestX
{
public static void main(String args[])
{
String someString = "Your input";
System.out.println(someString + " " + args[0]);
int resultOfSomething = 45;
String someOutput = "Program's output is " + resultOfSomething;
System.out.println(someOutput);
}
}
And here is the Python script that calls the java program
import os.path,subprocess
from subprocess import STDOUT,PIPE
def compile_java(java_file):
subprocess.check_call(['javac', java_file])
def execute_java(java_file):
java_class,ext = os.path.splitext(java_file)
cmd = ['java', java_class]
proc = subprocess.Popen(cmd, stdout=PIPE, stderr=STDOUT)
stdout,stderr = proc.communicate(input='SomeInputstring')
print ('This was "' + stdout + '"')
compile_java('TestX.java')
execute_java('TestX.java')
I should mention that I am not familiar with java. I compiled the little java program by this command javac TestX.java. That created a class file. And when I run the java program from the command line using java TestX SomeTestString
the tiny java program works as expected and outputs some text to the console.
Now the problem; When I run the same java program from Python using the code above - 1) There is an error
This was "Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at TestX.main(TestX.java:7)
"
When I comment out the line print ('This was "' + stdout + '"')
in the Python program, then the Python program runs and seems to execute the java program, but nothing is returned to the console. There is something extremely simple that I am missing here or it's just a silly mistake that I made. Any pointers? Thanks.
I tried a few different methods to output the result, like by using printf, ,and even using this class StdOut. All of them seem to behave the same.
If I were to explain this in a nutshell, it's this; My Python script should call a java program with a single argument. The java program takes in the input, performs certain functions and returns a result which I should be able to read from the Python program that called it.
Upvotes: 3
Views: 5702
Reputation: 1374
For your requirement (execute a java file passing a single argument from Python and after execution, return the result back to the script that called it), Popen is not reccomended. This is because it is non-blocking. The code does not wait for the output to be returned. Please use the subprocess.run() command for Python > 3.7.
result = subprocess.run(
['java', '-cp', EXTERNAL_JAR_PATHS, 'MyJavaCode.java', ARGUMENT],
capture_output = True,
text = True,
cwd = PATH_TO_CODE
)
result.stdout gives the program output and result.stderr gives information on errors if any.
Why this is better than debugging the Popen code:
Having said that in your case the immediate issue/error is correctly solved by Elliot. My approach addresses the larger requirement outlined in your last paragraph
Upvotes: 1
Reputation: 201537
Command line arguments are not stdin. args[0]
is a command line argument. You should be able to do it like
cmd = ['java', java_class, 'SomeInputString']
Upvotes: 3