External python application is not running - java

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();
....

Related

Running cscript //U (Unicode) from Java fails on some Windows versions

I have a Java application that runs cscript.exe to execute a simple VBScript. For illustration purposes, the content of the script (test.vbs) is this:
Wscript.Echo "ready"
The simplified Java code looks like this:
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class Test
{
static boolean useUnicode = false;
public static void main(String args[]) throws Exception
{
String unicodeOpt = useUnicode ? "//U" : "";
Charset charset = useUnicode ? StandardCharsets.UTF_16LE : Charset.defaultCharset();
Process p = Runtime.getRuntime().exec("cscript " + unicodeOpt + " //NoLogo test.vbs");
InputStream pin = p.getInputStream();
BufferedReader input = new BufferedReader(new InputStreamReader(pin, charset));
System.out.println("Available: " + pin.available());
System.out.println("Output: " + input.readLine());
}
}
This works fine if useUnicode is false:
Available: 7
Output: ready
However when useUnicode is true (this passes //U to cscript) it does not work; the input stream returned by p.getInputStream() reports 0 bytes available in this case:
Available: 0
Output: null
Running the same script from the command line (cscript //U //NoLogo test.vbs) works fine.
Why isn't this working when I run the same command from Java?
Edit: The problem only happens on some Windows machines. I have been able to reproduce it on Windows 7 and Windows 10 boxes, but not in all of them. Even in the cases where the problem can be reproduced with the Java code, running the script from the command line always works. I cannot find an explanation for this.
Try the following and look in the file 'output.txt' in the current directory for the output. NB I have now simplified the code and tested in Windows:
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class Test {
public static void main(String args[]) throws Exception {
boolean useUnicode = false;
Charset charset = useUnicode ? StandardCharsets.UTF_16LE : Charset.defaultCharset();
String[] command = { "cscript.exe", "/u", "/nologo", "test.vbs" };
System.out.println("Executing command " + java.util.Arrays.toString(command));
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
Process p = pb.start();
InputStream pin = p.getInputStream();
try (Reader input = new BufferedReader(new InputStreamReader(p.getInputStream(), charset));
Writer out = Files.newBufferedWriter(Path.of("output.txt"), charset)) {
input.transferTo(out);
}
}
}
Running in Windows:
C:\Users\User\AppData\Local\Temp>java Test
Executing command [cscript.exe, /u, /nologo, test.vbs]
C:\Users\User\AppData\Local\Temp>type output.txt
e a d y
Yes, naturally type cannot cope with Unicode, hence the weird output but the file opens properly in write.exe.

java runtime environment no result

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()

Converting interactive shell output to plain text

I am trying to view the temperature table for my CPU on my Linux machine with Java. This bit of code will display the shell output for other commands, ls, cat file, but will not display watch sensors as it returns an interactive output. Is there a way I can convert it to plain text somehow?
Error: [/usr/bin/watch, sensors]
Error opening terminal: unknown.
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 tempapp{
public static void main (String args[]) throws IOException, InterruptedException {
//build command
List<String> commands = new ArrayList<String>();
commands.add("/usr/bin/watch");
//args
commands.add("sensors");
System.out.println(commands);
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("/home/ethano"));
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("\n success");
System.exit(0);
}
//weird termination
System.err.println(commands);
System.err.println(out.toString());
System.exit(1);
}
}
All that watch does is call the command it is given (sensors in this case) once every two seconds. You can simply have your application emulate this behaviour by calling /usr/bin/sensors in a for-loop once every two seconds (or however many times you need), therefore omitting the need to read interactive shell output.

Java - Run Powershell and parse commands to it

iam working on a project for a Service Desk. This Service Desk have round about 10 various tools to get the result for the customers. I already have put this tools to one Java-Tool together.
One thing do not want work.
The customers work on several XenApp/XenDesktop Servers. From the Server the customers ar loged in, i wanna get the RAM Avarage Util to show them in the GUI of my tool.
I wanne run a powershell ones and paste multiple times commands to the powershell. But it want work. In my example the program hangs in the while loop
while(!file.exists() & !file.canWrite()){}
after it runs one time.
My question is, can i run a powershell once and paste commands to it multiple times? In C# ive tryed it and it works. But i want rewrite 7000 lines of code in C#.
Sorry for my bad english. I hope you understand my problem and can help me.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import javax.security.auth.login.LoginException;
public class SystemAvarageUtil {
public static void getSystemAvarageUtil(String desktopServer, String appServer, String personalNummer) throws IOException, InterruptedException{
final Process process = Runtime.getRuntime().exec("PowerShell -NoExit -Command -");
while(personalNummer.equals("XXXXXX")){
File file = new File("H:\\sdassistence\\tmp\\Util.tmp");
if(file.exists()){
file.delete();
}
PrintWriter commands = new PrintWriter(process.getOutputStream(),true);
//desktopServer RAM
commands.println("$ComputerNameDesktop=\""+ desktopServer +"\"");
commands.println("$ComputerSystemDesktop = Get-WmiObject -ComputerName $ComputerNameDesktop -Class Win32_operatingsystem -Property CSName, TotalVisibleMemorySize, FreePhysicalMemory");
commands.println("$MachineNameDesktop = $ComputerSystemDesktop.CSName");
commands.println("$FreePhysicalMemoryDesktop = ($ComputerSystemDesktop.FreePhysicalMemory) / (1mb)");
commands.println("$TotalVisibleMemorySizeDesktop = ($ComputerSystemDesktop.TotalVisibleMemorySize) / (1mb)");
commands.println("$TotalVisibleMemorySizeRDesktop = \"{0:N2}\" -f $TotalVisibleMemorySizeDesktop");
commands.println("$TotalFreeMemPercDesktop = ($FreePhysicalMemoryDesktop/$TotalVisibleMemorySizeDesktop)*100");
commands.println("$TotalFreeMemPercRDesktop = \"{0:N2}\" -f $TotalFreeMemPercDesktop");
//commands.println("$TotalVisibleMemorySizeRDesktop GB");
//commands.println("$TotalFreeMemPercRDesktop %");
//appServer RAM
commands.println("$ComputerNameApp=\""+ appServer +"\"");
commands.println("$ComputerSystemApp = Get-WmiObject -ComputerName $ComputerNameApp -Class Win32_operatingsystem -Property CSName, TotalVisibleMemorySize, FreePhysicalMemory");
commands.println("$MachineNameApp = $ComputerSystemApp.CSName");
commands.println("$FreePhysicalMemoryApp = ($ComputerSystemApp.FreePhysicalMemory) / (1mb)");
commands.println("$TotalVisibleMemorySizeApp = ($ComputerSystemApp.TotalVisibleMemorySize) / (1mb)");
commands.println("$TotalVisibleMemorySizeRApp = \"{0:N2}\" -f $TotalVisibleMemorySizeApp");
commands.println("$TotalFreeMemPercApp = ($FreePhysicalMemoryApp/$TotalVisibleMemorySizeApp)*100");
commands.println("$TotalFreeMemPercRApp = \"{0:N2}\" -f $TotalFreeMemPercApp");
//commands.println("$TotalVisibleMemorySizeRApp GB");
//commands.println("$TotalFreeMemPercRApp %");
commands.println("$TotalVisibleMemorySizeRDesktop+\";\"+$TotalFreeMemPercRDesktop+\";\"+$TotalVisibleMemorySizeRApp+\";\"+$TotalFreeMemPercRApp | Out-File -Encoding UTF8 -FilePath \"H:\\sdassistence\\tmp\\Util.tmp\"");
commands.println("exit");
commands.close();
while(!file.exists() & !file.canWrite()){}
Thread.sleep(1000);
FileReader fr = new FileReader(file);
BufferedReader in = new BufferedReader(fr);
String test[] = in.readLine().split(";");
System.out.println(test[0] + " " + test[1] + " " + test[2]);
fr.close();in.close();process.destroy();
}
}
public static void main(String[] args) throws LoginException, IOException, InterruptedException {
getSystemAvarageUtil("DesktopServer","AppServer","XXXXXX");
}
}

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