Java - How to call python classes using processbuilder - java

How do I call and execute python class methods from java. My current java code works, but only if I write:
if __name__ == '__main__':
print("hello")
But I want to execute a class method, regardless of if __name__ == '__main__':
Example python class method I would like to run:
class SECFileScraper:
def __init__(self):
self.counter = 5
def tester_func(self):
return "hello, this test works"
Essentially I would want to run SECFileScraper.tester_func() in java.
My Java code:
try {
ProcessBuilder pb = new ProcessBuilder(Arrays.asList(
"python", pdfFileScraper));
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) {
e.printStackTrace();
}
pdfFileScraper is the file path to my python script.
I've tried jython, but my python files use pandas and sqlite3, which can't be implemented using jython.

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

This is my java class that worked for me.
class PythonFileReader {
private String path;
private String fileName;
private String methodName;
PythonFileReader(String path, String fileName, String methodName) throws Exception {
this.path = path;
this.fileName = fileName;
this.methodName = methodName;
reader();
}
private void reader() throws Exception {
StringBuilder input_result = new StringBuilder();
StringBuilder output_result = new StringBuilder();
StringBuilder error_result = new StringBuilder();
String line;
String module = fileName.substring(0, fileName.lastIndexOf('.'));
String command = "import " + module + "; " + module + "." + module + "." + methodName;
List<String> items = Arrays.asList("python", "-c", command);
ProcessBuilder pb = new ProcessBuilder(items);
pb.directory(new File(path));
Process p = pb.start();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader out = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((line = in.readLine()) != null)
input_result.append("\n").append(line);
if (input_result.length() > 0)
System.out.println(fileName + " : " + input_result);
while ((line = out.readLine()) != null)
output_result.append(" ").append(line);
if (output_result.length() > 0)
System.out.println("Output : " + output_result);
while ((line = error.readLine()) != null)
error_result.append(" ").append(line);
if (error_result.length() > 0)
System.out.println("Error : " + error_result);
}}
and this is the way that you can use this class
public static void main(String[] args) throws Exception {
String path = "python/path/file";
String pyFileName = "python_name.py";
String methodeName = "test('stringInput' , 20)";
new PythonFileReader(path, pyFileName, methodeName );
}
and this is my python class
class test:
def test(name, count):
print(name + " - " + str([x for x in range(count)]))

Related

Java: Run main of another class and get the stdout of that class

I am running something like this
String[] reassignCmdArgs =
{ "--reassignment-json-file=" + jsonFile,
"--zookeeper=" + zkConnect,
"--throttle=" + (throttle <= 0 ? "1000000000" : throttle),
"--execute" };
ReassignPartitionsCommand.main(reassignCmdArgs);
The ReassignPartitionsCommand has some println statements and I would like to capture those here.
How can this be done?
EDIT:
My current workaround is below. I'm looking for something that does not start another process
String[] reassignCmdArgs =
{ "--reassignment-json-file=" + jsonFile,
"--zookeeper=" + zkConnect,
"--throttle=" + (throttle <= 0 ? "1000000000" : throttle),
"--execute" };
System.out.println("Calling ReassignPartitionsCommand with args: " +
Arrays.toString(reassignCmdArgs));
StringBuilder result = new StringBuilder();
try {
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader) cl).getURLs();
ProcessBuilder pb = new ProcessBuilder();
pb.redirectErrorStream(true);
String classPath = Arrays.asList(urls)
.stream()
.map(URL::getFile)
.collect(Collectors.joining(";"));
String[] args = new String[4 + reassignCmdArgs.length];
args[0] = "java";
args[1] = "-cp";
args[2] = classPath;
args[3] = ReassignPartitionsCommand.class.getName();
for (int i = 4; i < 4 + reassignCmdArgs.length; i++) {
args[i] = reassignCmdArgs[i - 4];
}
pb.command(args);
System.out.println("Calling process with args: " + Arrays.toString(args));
Process p = pb.start();
p.waitFor(); // wait for process to finish
BufferedReader bri =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = bri.readLine()) != null) {
result.append(line + "\n");
}
} catch (Exception e) {
result = new StringBuilder("Problem running as another process");
ReassignPartitionsCommand.main(reassignCmdArgs);
}
You should look at ProcessBuilder; you can specify where the output goes e.g. pb.redirectOutput(Redirect.appendTo(log)). Then simply read the output from the file you specify.

Not able to import csv file into mongodb available in Remote location from java?

Runtime r = Runtime.getRuntime();
String cmd = "C:\\Program Files (x86)\\MongoDB\\Server\\3.0\\bin\\mongoimport -d dummydb -c Employee --type csv --file /home/mongodb/one.csv --headerline";
r.exec(cmd);
When I ran same command in linux machine, csv file imported. But, from java standalone I am not able to insert.
Could you please help on this.
Please try the below code after changing the collection name, database name and file path. It should work.
Note:-
Need to mention mongoimport.exe - as present in the below code.
Code:-
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class MongoImportUtil {
public static void main(String[] args) {
String db = "test";
String col = "Account";
String Host = "localhost";
String Port = "27017";
String fileName = "D:/files/sample.csv";
String command = "C:\\Program Files\\MongoDB\\Server\\3.4\\bin\\mongoimport.exe --host " + Host + " --port "
+ Port + " --db " + db + " --collection " + col + " --headerline --type=csv --file " + fileName;
try {
System.out.println(command);
Process process = Runtime.getRuntime().exec(command);
int waitFor = process.waitFor();
System.out.println("waitFor:: " + waitFor);
BufferedReader success = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String s = "";
while ((s = success.readLine()) != null) {
System.out.println(s);
}
while ((s = error.readLine()) != null) {
System.out.println("Std ERROR : " + s);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Ghostscript Error when executing from Java

I am trying to execute a ghostscript command from my Java Program using Runtime.getRuntime().exec(command).
The command that i am using to generate PDF/A File is:
command = "/usr/local/bin/gs -q -dPDFA=2 -dBATCH -dNOPAUSE -sColorConversionStrategy=RGB -sDEVICE=pdfwrite -dPSFitPage -dFastWebView=true -dDOPDFMARKS -sOutputFile=" + mergedPDFFile + " " + pdfaDefFile + " " + inputPDFFile + " " + pdfMarksFile;
It works perfectly fine when the input PDF file size is less than 1 MB. However, when the input PDF File size is greater than 1 MB, the output does not get generated.
The code that i have written in Java is:
private void executeCommand(String command) {
Process p = null;
try {
p = Runtime.getRuntime().exec(new String[]{"bash", "-c", command});
String s1 = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((s1= reader.readLine()) != null) {
slf4jLogger.info("+++++++++++++++++++++++++++++" + s1);
}
String s = null;
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((s = stdError.readLine()) != null) {
slf4jLogger.info("***********************" + s);
}
p.waitFor();
int returnValue = p.exitValue();
slf4jLogger.info("RETURN VALUE : " + returnValue);
} catch (Throwable e) {
slf4jLogger.error("ERROR: ********************" + e.toString(), e);
} finally {
slf4jLogger.info("END MY PROCESS:");
if (p != null) {
p.destroy();
}
}
Any help is greatly appreciated.

How can I close a Java application from another Java application?

I am using the following code for running an application:
private void RunApp2() throws IOException
{
StringBuilder sb = new StringBuilder();
String filePath = System.getProperty("user.dir");
String jarfile = filePath + "\\MyAppV2.jar";
File f = new File(jarfile);
if(f.exists() && !f.isDirectory()) {
// do something
}
else
{
AreThereProblem = true;
}
try { // jarname arguments has to be saperated by spaces
Process process = Runtime.getRuntime().exec("cmd.exe start /C java -jar \""+jarfile + "\"");
//.exec("cmd.exe /C start dir java -jar "+jarfile+" "+name+" "+id+" dir");
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream ()));
String line = null;
while ((line = br.readLine()) != null){
sb.append(line).append("\n");
}
System.out.println("Console OUTPUT : \n"+sb.toString());
//process.destroy();
}catch (Exception e){
lblInformation.setText(e.getMessage());
}
}
But how can I close MyAppV2.jar application if it is already running before I'm running it again?

executing java commands from another java file

public String runMsg(String fileName, File Path, int option)
{
int x = 0;
String name = " ", ret = "";
if (option == 1) {
x = fileName.indexOf(".c");
name = fileName.substring(0, x);
command = name + ".exe < C:\\iptest\\input.txt > C:\\outtest\\" + name + ".txt";
} else if (option == 2) {
x = fileName.indexOf(".cpp");
name = fileName.substring(0, x);
command = name + ".exe < C:\\iptest\\input.txt > C:\\outtest\\" + name + ".txt";
} else {
x = fileName.indexOf(".java");
name = fileName.substring(0, x);
command = "java " + name + " < C:\\iptest\\input.txt > C:\\outtest\\" + name + ".txt";
}
String output = executeCommand(command, Path);
}
private String executeCommand(String command, File Path)
{
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command, null, Path);
p.waitFor();
BufferedReader reader1 = new BufferedReader(new InputStreamReader(p.getErrorStream()));
BufferedReader reader2 = new BufferedReader(new InputStreamReader(p.getInputStream()));
// BufferedReader reader3 = new BufferedReader(new InputStreamReader(p.getOutputStream()));
String line = "";
while ((line = reader1.readLine()) != null) {
output.append(line + "\n");
}
while ((line = reader2.readLine()) != null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
I am trying to execute a .class file from another java file. The .java file will take input from a txt file located at C:\iptest\input.txt and will produce an output file at the following location C:\outputtest\out.txt but when I run this application nothing happens and the application goes into some kind of infinite loop.

Categories

Resources