java runtime environment no result - java

I am trying to call python within my java code. However I found that if I import numpy in my python code, this is my java code
Process pcs = Runtime.getRuntime().exec(cmd);
String result = null;
BufferedInputStream in = new BufferedInputStream(pcs.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
System.out.println("\nExecuting python script file now.");
String lineStr = null;
while ((lineStr = br.readLine()) != null) {
result = lineStr;
}
br.close();
in.close();
System.out.println("done!");
System.out.println(result);
This is my python code:
import sys
import os
import numpy as np
a = sys.argv[1]
b = sys.argv[2]
print("hello world!")
print("%s * %s = %s"%(a,b,int(a)*int(b)))
Results if I don't include "import numpy as np":
10 * 11 = 110
Results if include "import numpy as np":
null
Any intuitive explanation?

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Hello{
public static void main(String[] args)throws java.io.IOException{
Process pcs=Runtime.getRuntime().exec("python test.py 8 5");// in linux or unix use python3 or python
String result=null;
BufferedInputStream in = new BufferedInputStream(pcs.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
System.out.println("\nExecuting python script file now.");
String lineStr = null;
while ((lineStr = br.readLine()) != null) {
result = lineStr;
}
br.close();
in.close();
System.out.println("done!");
System.out.println(result);
}
}
java code
compile:
javac Hello.java
run:
java Hello
#test.py
import sys
import os
import numpy as np
a = sys.argv[1]
b = sys.argv[2]
print("hello world!")
print("%s * %s = %s"%(a,b,int(a)*int(b)))

Have you got the right PYTHONPATH setup in your application? When you have import numpy as np in your code, you may be receiving back empty STDOUT and an ModuleNotFoundError in STDERR. You can confirm by extracting STDERR - or check with this code:
Launch.exe(cmd);
where Launch.java is:
public class Launch
{
/** Launch using FILE redirects */
public static int exec(String[] cmd) throws InterruptedException, IOException
{
System.out.println("exec "+Arrays.toString(cmd));
Path tmpdir = Path.of(System.getProperty("java.io.tmpdir"));
ProcessBuilder pb = new ProcessBuilder(cmd);
Path out = tmpdir.resolve(cmd[0]+"-stdout.log");
Path err = tmpdir.resolve(cmd[0]+"-stderr.log");
pb.redirectError(out.toFile());
pb.redirectOutput(err.toFile());
Process p = pb.start();
int rc = p.waitFor();
System.out.println("Exit "+rc +' '+(rc == 0 ? "OK":"**** ERROR ****")
+" STDOUT \""+Files.readString(out)+'"'
+" STDERR \""+Files.readString(err)+'"');
System.out.println();
return rc;
}
}
The fix for using numpy should be to access ProcessBuilder pb.environment() and set your PYTHONPATH for the subprocess before calling start()

Related

Java enter command to a process that opens a new telnet connection

I would like to write a Java program to control the Android emulator to do some testing, and now I have to take snapshots of the emulator when it is created and every time it has changes, so according to google, the command is like:
telnet localhost 5555
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Android Console: type 'help' for a list of commands
OK
avd snapshot save 1
OK
So basically two commands, the first is to open a telnet connection and then enter avd snapshot save x command to save the snapshot.
However using the command like this:
public static void main(String[] args) throws IOException{
int initScore = 1000;
int ID = 0;
// monitor the log, check if a new activity is reached.
// if so, take a snapshot of the current activity and save it to the snapshot folder.
String cmd1 = "telnet localhost " + 5555;
// the static port 5557 should change to this.getVM_consolePort();
String cmd2 = "avd snapshot save " + ID;
ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", cmd1, cmd2);
Process p = pb.start();
// read the process output
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
}
can only run the first command (which is to open telnet connection).
So could anyone tell me how to interact with a opened connection or enter command to another process in Java?
Here's an example using grep:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class Test {
public static void main(String[] args) throws IOException {
ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", "grep foo");
Process p = pb.start();
BufferedReader stdOut = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdErr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
Writer stdIn = new OutputStreamWriter(p.getOutputStream());
stdIn.write("foo1\nbar\nfoo2\n");
stdIn.close();
String s = null;
while ((s = stdOut.readLine()) != null) {
System.out.println(s);
}
while ((s = stdErr.readLine()) != null) {
System.out.println(s);
}
}
}
I renamed stdIn to stdOut, so they are named from the point of view of the process you're running.
I read from stderr, so that you can see any problems.
Actually I have tried this before like the code below:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
public class Main {
public static void main(String[] args) throws IOException {
// int initScore = 1000;
int ID = 0;
Process p = Runtime.getRuntime().exec("telnet localhost 5555");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedWriter stdIn = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
String line;
while ((line = stdInput.readLine()) != null) {
System.out.println(line);
if (line.contains("OK")){
break;
}
}
stdIn.write("avd snapshot save " + ID);
while ((line = stdInput.readLine()) != null) {
System.out.println(line);
}
}
}
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Android Console: type 'help' for a list of commands
OK
I think the reason is that the telnet created a new shell and the writer is writing to the old shell, therefore it is not working, so I am looking for a solution to enter the new command into the new shell.

External python application is not running

Hi i just create a java application to run my python code externally. But it want giving me the out put.
this is my java code:-
package com.epatient;
import java.io.*;
public class InterpreterExample {
//static String workingDir = System.getProperty("user.dir");
//static String appDir = workingDir + "\\epatient\\epatient_prediction.py";
public static void main(String a[]){
try{
String appDir = "C:\\Users\\Thushara Kasun\\Documents\\juno\\serial.port\\epatient\\epatient_prediction.py";
System.out.println(appDir);
ProcessBuilder pb = new ProcessBuilder("python",appDir);
Process p = pb.start();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String ret = in.readLine();
System.out.println("value is : "+ret);
}catch(NumberFormatException e){e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
}
}
this is my python code :-
import sys
from sklearn.externals import joblib
import pandas as pd
import numpy as np
import csv
from sklearn.decomposition import PCA
import re
import psycopg2
import datetime
import time
con = None
bio_data = None
heart_rate = None
so2_data = None
temp_data = None
bp_data = None
try:
con = psycopg2.connect(database='Epatient_user_1', user='postgres', password='root')
cur = con.cursor()
...#database access codes omited
model_name = 'trained_model'
est = joblib.load(model_name)
predictions = est.predict(data)
#predictions
# <codecell>
#sys.stdout.write(str(int(predictions[0])))
#sys.stdout.flush()
#print int(predictions[0])
ts = time.time()
st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
#print st
cur.execute('INSERT INTO patient_status (STATUS,TIME,PROCESSED) VALUES (' + str(int(predictions[0])) + ',\''+ st + '\',0);')
con.commit()
except psycopg2.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if con:
con.close()
sys.stdout.write(str(int(predictions[0])))
sys.stdout.flush()
#print int(predictions[0])
Java out put is just value is : null
there is no problem with the python code it is working perfectly. i just want to print a Boolean which is in a string format. simultaneously i need to update that value in my local postgresql database(via python code, which is working individually). simply the python code is not executing by my java application. Kindly help me on this or give me a alternative way to resolve this issue.
I think that your Java code is Ok, then try to change your Python script.
Please, would you be so kind to change the line print int(predictions[0]) with:
sys.stdout.write(str(predictions[0]))
sys.stdout.flush()
sys.stdout will print data to console outputstream
and just for testing, put the absolute path of your script in the ProcessBuilder constructor:
String appDir = "C:\\my\\full\\path\\to\\script.py";
ProcessBuilder pb =
new ProcessBuilder("python", appDir);
Process p = pb.start();
....

Run Bash Script File from JAVA

I work with Bash script. My bash script is
#!/bin/bash
function aa(){
echo "Run";
su - postgres -c "shp2pgsql -I -s 4269 /tmp/gismanager/Wards.shp ff | psql postgis;";
echo "Run";
return 0;
}
aa;
when this script run by linux result is Run Run but from java result is Run
my java code is
public static void execShellCmd(String path) {
try {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(path);
BufferedReader buf = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = buf.readLine()) != null) {
System.out.println("exec response: " + line);
}
} catch (Exception e) {
System.out.println(e);
}
}
Can anybody help me?
Have you tried to capture the OutputStream and ErrorStream?
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
InputStream inputStream = process.getInputStream();
InputStream errorStream = process.getErrorStream();
BufferedReader inputReader = new BufferedReader(new InputStreamReader(inputStream));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream));

How to run a Perl file using Java? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How should I call a Perl Script in Java?
I have a perl file which is used for remotely checking ip addresses.I need to run that perl in java.please help me to proceed.
ProcessBuilder example
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import org.apache.commons.io.FileUtils;
OutputStreamWriter writer =null;
BufferedReader stdoutBR = null;
try {
File tmp = new File("temp_dir");
File cmdFile = File.createTempFile("foo", ".sh", tmp);
File stdout = File.createTempFile("foo_stdout", ".txt", tmp);
File stderr = File.createTempFile("foo_stderr", ".txt", tmp);
String script = "/usr/bin/perl foo.pl 2>"+stderr.getAbsolutePath()+" >"+stdout.getAbsolutePath()+" \n";
cmdFile.setExecutable(true);
FileUtils.writeStringToFile(cmdFile, script);
ProcessBuilder processBuilder = new ProcessBuilder(cmdFile.getAbsolutePath());
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
InputStream numbStream = process.getInputStream();
stdoutBR = new BufferedReader(new InputStreamReader(numbStream));
String line = null;
StringBuilder unexpectedOutput = new StringBuilder();
while ((line = stdoutBR.readLine()) !=null) {
unexpectedOutput.append(line);
unexpectedOutput.append("\n");
}
process.waitFor();
stdoutBR.close();
log.debug("Process exit value:"+process.exitValue());
if (process.exitValue() != 0) {
String stdoutString = FileUtils.readFileToString(stdout);
String stderrString = FileUtils.readFileToString(stderr);
throw new RuntimeException("Problem executing script. \nOutput:"+unexpectedOutput.toString()+"\nStdout:"+stdoutString+"\nStderr:"+stderrString);
}
String output = FileUtils.readFileToString(stdout);
FileUtils.deleteQuietly(cmdFile);
FileUtils.deleteQuietly(stdout);
FileUtils.deleteQuietly(stderr);
} finally {
try {
if (writer != null) {
writer.close();
}
}
catch (Exception e) {
//TODO
}
}
You need the Runtime.getRuntime().exec() method. Some points to consider:
you must explicitly call perl in the command line: "perl myprog.pl". The implicit interpreter selection that the kernel normally does doesn't work in the exec() method.
you must make sure that the path to perl is in your program's PATH environment,
or in the environment that you pass to the exec() call
you must completely drain the stdout and the stderr of the Process that you created, or the call will not terminate.
(The ProcessBuilder class mentioned above simplifies some of these issues.)

How to invoke a Linux shell command from Java

I am trying to execute some Linux commands from Java using redirection (>&) and pipes (|). How can Java invoke csh or bash commands?
I tried to use this:
Process p = Runtime.getRuntime().exec("shell command");
But it's not compatible with redirections or pipes.
exec does not execute a command in your shell
try
Process p = Runtime.getRuntime().exec(new String[]{"csh","-c","cat /home/narek/pk.txt"});
instead.
EDIT::
I don't have csh on my system so I used bash instead. The following worked for me
Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","ls /home/XXX"});
Use ProcessBuilder to separate commands and arguments instead of spaces. This should work regardless of shell used:
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(final String[] args) throws IOException, InterruptedException {
//Build command
List<String> commands = new ArrayList<String>();
commands.add("/bin/cat");
//Add arguments
commands.add("/home/narek/pk.txt");
System.out.println(commands);
//Run macro on target
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("/home/narek"));
pb.redirectErrorStream(true);
Process process = pb.start();
//Read output
StringBuilder out = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null, previous = null;
while ((line = br.readLine()) != null)
if (!line.equals(previous)) {
previous = line;
out.append(line).append('\n');
System.out.println(line);
}
//Check result
if (process.waitFor() == 0) {
System.out.println("Success!");
System.exit(0);
}
//Abnormal termination: Log command parameters and output and throw ExecutionException
System.err.println(commands);
System.err.println(out.toString());
System.exit(1);
}
}
Building on #Tim's example to make a self-contained method:
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Shell {
/** Returns null if it failed for some reason.
*/
public static ArrayList<String> command(final String cmdline,
final String directory) {
try {
Process process =
new ProcessBuilder(new String[] {"bash", "-c", cmdline})
.redirectErrorStream(true)
.directory(new File(directory))
.start();
ArrayList<String> output = new ArrayList<String>();
BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = null;
while ( (line = br.readLine()) != null )
output.add(line);
//There should really be a timeout here.
if (0 != process.waitFor())
return null;
return output;
} catch (Exception e) {
//Warning: doing this is no good in high quality applications.
//Instead, present appropriate error messages to the user.
//But it's perfectly fine for prototyping.
return null;
}
}
public static void main(String[] args) {
test("which bash");
test("find . -type f -printf '%T#\\\\t%p\\\\n' "
+ "| sort -n | cut -f 2- | "
+ "sed -e 's/ /\\\\\\\\ /g' | xargs ls -halt");
}
static void test(String cmdline) {
ArrayList<String> output = command(cmdline, ".");
if (null == output)
System.out.println("\n\n\t\tCOMMAND FAILED: " + cmdline);
else
for (String line : output)
System.out.println(line);
}
}
(The test example is a command that lists all files in a directory and its subdirectories, recursively, in chronological order.)
By the way, if somebody can tell me why I need four and eight backslashes there, instead of two and four, I can learn something. There is one more level of unescaping happening than what I am counting.
Edit: Just tried this same code on Linux, and there it turns out that I need half as many backslashes in the test command! (That is: the expected number of two and four.) Now it's no longer just weird, it's a portability problem.

Categories