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);}
}
}
Answer from shazin on Stack OverflowUsually 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.
How to start a python process from Java and do IO communication?
Java/python using processBuilder - Stack Overflow
Running python from Java using Process Builder - Stack Overflow
Java - How to call python classes using processbuilder - Stack Overflow
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
So if I understand your requirement, you want to invoke a class method in pdfFileScraper.py. The basics of doing this from the shell would be something akin to:
scraper=path/to/pdfFileScraper.py
dir_of_scraper=$(dirname $scraper)
export PYTHONPATH=$dir_of_scraper
python -c 'import pdfFileScraper; pdfFileScraper.ClassInScraper()'
What we do is get the directory of pdfFileScraper, and add it to the PYTHONPATH, then we run python with a command that imports the pdfFileScraper file as a module, which exposes all the methods and classes in the class in the namespace pdfFileScraper, and then construct a class ClassInScraper().
In java, something like:
import java.io.*;
import java.util.*;
public class RunFile {
public static void main(String args[]) throws Exception {
File f = new File(args[0]); // .py file (e.g. bob/script.py)
String dir = f.getParent(); // dir of .py file
String file = f.getName(); // name of .py file (script.py)
String module = file.substring(0, file.lastIndexOf('.'));
String command = "import " + module + "; " + module + "." + args[1];
List<String> items = Arrays.asList("python", "-c", command);
ProcessBuilder pb = new ProcessBuilder(items);
Map<String, String> env = pb.environment();
env.put("PYTHONPATH", dir);
pb.redirectErrorStream();
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);
}
}
}
You can also call Python lib directly via JNI. This way, you don't start new process, you can share context between script calls, etc.
Take a look here for a sample:
https://github.com/mkopsnc/keplerhacks/tree/master/python
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();