Pass two separate arguments to ProcessBuilder instead of concatenating --arg1 and argumentValue:
ProcessBuilder builder = new ProcessBuilder("C:\\Python33\\python.exe",
"-u",
"C:\\...\\script.py,
"--arg1",
"argumentValue");
Otherwise the program to be executed will see a single argument --arg1 argumentValue that it does not recognise.
Java ProcessBuilder not able to run Python script in Java - Stack Overflow
java - Process Builder error while running Python script by passing arguments - Stack Overflow
How to execute a python file with some arguments in java - Stack Overflow
java - Using ProcessBuilder to execute a python script with command line options - Stack Overflow
Usually when executing commands using ProcessBuilder, PATH variable is not taken into consideration. Your python C:/Machine_Learning/Text_Analysis/Ontology_based.py is directly working in your CMD shell because it can locate the python executable using the PATH variable. Please provide the absolute path to python command in your Java code. In below code replace <Absolute Path to Python> with the path to python command and its libraries. Usually it will something like C:\Python27\python in Windows by default
package text_clustering;
import java.io.*;
public class Similarity {
/**
*
* @param args
*
*/
public static void main(String[] args){
try{
String pythonPath = "C:/Machine_Learning/Text_Analysis/Ontology_based.py";
//String pythonExe = "C:/Users/AppData/Local/Continuum/Anaconda/python.exe";
ProcessBuilder pb = new ProcessBuilder(Arrays.asList("<Absolute Path to Python>/python", pythonPath));
Process p = pb.start();
BufferedReader bfr = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
System.out.println("Running Python starts: " + line);
int exitCode = p.waitFor();
System.out.println("Exit Code : "+exitCode);
line = bfr.readLine();
System.out.println("First Line: " + line);
while ((line = bfr.readLine()) != null){
System.out.println("Python Output: " + line);
}
}catch(Exception e){System.out.println(e);}
}
}
Reading from stdin returns null when the script is killed/dies. Do a Process#waitFor and see what the exitValue is. If it isn't 0 then it's highly probable that your script is dying.
I'd try making it work with a dumb script that only writes a value. Make sure that you print all error information from python.
I'm a python dev, like I know literally no Java. But because I'm experienced in python I can at least kinda understand what I'm doing in Java. But I'm stuck on this. I know it's basic shit, I can do this in python, but I just can't read the language so I can't read any help or guides either.
All I need to do really is start a python program from Java as a subprocess, receive it's output stream and be able to send to its input stream.
The python program is a discord bot using async/await stuff and will run continuously so it needs to be uninterrupted, like if it was run from the terminal EXCEPT the Java program can send input and receive output.
I also suck att processes and stuff (this is on Windows btw) and as I said I suck at Java too so sorry if I gave to little information or something. Just tell me if that's the case.
Thanks in advance :D
You can check the ProcessBuilder documentation over at Sunoracle, but basically, you can run the interpreter for the scripting language and pass the script you want to run to it.
For example, let's say you have a script in /home/myuser/py_script.py, and python is in /usr/bin/
class ProcessRunner
{
public static void main(String [] args)
{
ProcessBuilder pb = new ProcessBuilder("/usr/bin/python", "/home/myuser/py_script.py");
Process p = pb.start();
}
}
An extremely basic example, you can get fancier with changing the working directory and change the environment.
You can also construct ProcessBuilder with a String array or a subtype of List<String>. The first item in the list should be the program/executable you want to run, and all the following items are arguments to the program.
String pbCommand[] = { "/usr/bin/python", "/home/myuser/py_script.py" };
ProcessBuilder pb = new ProcessBuilder(pbCommand);
Process p = pb.start();
To avoid having to manually enter the entire location of the script, which may also result in portability issues, here's what I did:
String pwd = System.getProperty("user.dir");
ProcessBuilder pb = new ProcessBuilder("/usr/bin/python", pwd+'/'+scriptName, arg1, arg2);
Process p = pb.start();
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);