First off, there is a similar question here that wasn't ever really resolved.
I have a Python script that I want to execute from within my Java code. When I run the Python script on its own, it works properly. When I try to execute it from a Java process, I get an ImportError:
Traceback (most recent call last):
File "address_to_geocode.py", line 3, in <module>
from omgeo import Geocoder
ImportError: No module named omgeo
Per a suggestion from the linked question, I appended a direct path to the module in my Python import section to make sure the interpreter knows where to look, yet it still won't work:
import sys, os
sys.path.append('/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/omgeo')
from omgeo import Geocoder
My next move was to call the python script from a bash script (which again, works on its own), but when I call the bash script from Java, the same error persists. The issue, therefore seems to be on Java's end. Here is my java code:
Process p = runner.exec("python address_to_geocode.py");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String stdReader = null;
//Read output of command:
while((stdReader = stdInput.readLine())!=null) {
System.out.println(stdReader);
}
//Read any command errors:
while((stdReader = stdError.readLine())!=null) {
System.out.println(stdReader);
}
p.waitFor();
Is there anything wrong with my Java code or is this a bug? I appreciate any pointers.
I solved it. It looks like ProcessBuilder requires the full path not only to the python file itself, but to python:
ProcessBuilder("/Library/Frameworks/Python.framework/Versions/2.7/bin/python",absolute_file_path);
This solves the issue.
Find your python bin location
$ cat ~/.bash_profile
Java code
ProcessBuilder pb = new ProcessBuilder("/Users/micklin/anaconda2/bin/python","sentiment.py",done.toString());
code above is put in TweetFeeder.java so that .py file can be put under the project root
Related
I have this MCVE for an Java class calling a bash script:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
class Test
{
static BufferedReader in;
public static void main(String[] args) throws Exception
{
String[] cmd = new String[]{"/bin/sh", "/usr/myapp/myscript.sh", "parameter1"};
Process pr = Runtime.getRuntime().exec(cmd);
in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = in.readLine();
while(line != null)
{
System.out.println(line);
line = in.readLine();
}
}
}
When I have the compiled .class file in the same directory as myscript.sh, it works just fine.
As soon as I move the .class file to another folder, it doesn't execute the script anymore, although I am still using the absolute path to the script.
I tested this with JDK 1.8 on a BeagleboneBlack running Angstrom if this information is good for something.
How can I run the script, although it is in a different location?
Using the getErrorStream hint by Samuel really helped.
It was clear, that some sub-scripts that were in the same folder as the original shell script were not found.
The solution was as easy as using absolute paths to sub-scripts as well since the working directory is not the one of the called script but the one of the calling application (in my case the Java App)
I try to execute an external jar in my java application. The .jar is in my java-package ("gui").
I tried:
String filepath = this.getClass().getResource("ServerRSS.jar").getPath();
ProcessBuilder pb = new ProcessBuilder("java", filepath);
System.out.println(filepath); results in:
/C:/Users/hox/workspace/PraktikumProg/bin/gui/ServerRSS.jar
My programm doesn't start. Could the problem be the slash before the C: ?
EDIT:
The solution was:
URL filepath = this.getClass().getResource("ServerRSS.jar");
ProcessBuilder pb;
pb = new ProcessBuilder("java", "-jar", new File(filepath.toURI()).toString());
Process p = pb.start();
First get your command working ... simply on the command line.
And only then try to run it from within Java using a ProcessBuilder.
Simple answer is probably: to use -jar when invoking java.
java someJar.jar
does not work!
And yes, that slash matters big time. You simply want a fully correct file path there.
Finally: are you really sure you want to start a new JVM in order to run a main method in some class? You see, you could do that within your current JVM - without the additional performance and complexity cost of using a second JVM!
I am trying to call a python script from a java/tomcat6 webapp. I am currently using the following code:
Process p = Runtime.getRuntime().exec("python <file.py>");
InputStream in = p.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader b = new BufferedReader(isr);
logger.info("PYTHON OUTPUT");
String line = null;
while ( (line = b.readLine()) != null){
logger.info(line);
}
p.waitFor();
logger.info("COMPLETE PYTHON OUTPUT");
logger.info("EXIT VALUE: "+p.exitValue());
I can't really see any output in the catalinia.out file from the python script and using an adapter library like jython is not possible as the script relies on several machine learning libraries that need python's Numpy module to work.
Help?
The explanation is probably one (or more) of following:
The command is failing and writing error messages to its "stderr" fd ... which you are not looking at.
The command is failing to launch because the command name is incorrect; e.g. it can't be found on $PATH.
The command is trying to read from its stdin fd ... but you haven't provided any input (yet).
It could be a problem with command-line splitting; e.g if you are using pathnames with embedded spaces, or other things that would normally be handled by the shell.
Also, since this is python, this could be a problem with python-specific environment variables, the current directory and/or the effective user that is executing the command.
How to proceed:
Determine if the python command is actually starting. For instance. "hack" the "" to write something to a temporary file on startup.
Change to using ProcessBuilder to create the Process object. This will give you more control over the streams and how they are handled.
Find out what is going to the child processes "stderr". (ProcessBuilder allows you to redirect it to "stdout" ...)
In the project I am working on, I need to execute a script that I have in a resources folder -- in the class path. I am simply testing the final script functionality, since I am on Windows, I needed a way to output a file to STDIN so I created a simple cat.jar program to clone unixs cat command.
So when I do "java -jar cat.jar someFile.txt" it will output the file to stdout. I'm sure there are different ways of doing what I did.
Anyways,
I want to run that JAR from my main java program.
I am doing
Runtime.getRuntime().exec("java -jar C:/cat.jar C:/test.txt");
I've tried switching the forward slash to a backward slash and escaping it -- didn't work.
Nothing is getting sent to standard out.
Where as, if I run the cat jar on its own, I get the file directed to standard out.
What am I doing wrong here?
Is this enough information?
Use the Process instance returned by exec()
Process cat = Runtime.getRuntime().exec("java -jar C:/cat.jar C:/test.txt");
BufferedInputStream catOutput= new BufferedInputStream(cat.getInputStream());
int read = 0;
byte[] output = new byte[1024];
while ((read = catOutput.read(output)) != -1) {
System.out.println(output[read]);
}
References:
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
By default, the created subprocess does not have its own terminal or console. All its standard I/O (stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed via the streams obtained using the methods getOutputStream(), getInputStream(), and getErrorStream().
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html#getInputStream()
getInputStream() returns the input stream connected to the normal output of the subprocess.
I'm making an update function for my project, it's working great, until i want it to restart, basically I download the new file and replace it with the old one, and then i want to run it again, now for some reason it doesn't wna run, and i don't get any error...
Here is the complete update class:
http://dl.dropbox.com/u/38414202/Update.txt
Here is the method i'm using to run my .jar file:
String currDir = new File("(CoN).jar").getAbsolutePath();
Process runManager = Runtime.getRuntime().exec("java -jar " + currDir);
It's not clear to me, why do you need to run the jar with a call to exec() . Given that you need to run the code in the .jar file from a Java program, you could simply run the main() method as defined in the jar's manifest, and capture its output - wherever that is.
Using exec() is OK when you need to call a program from the underlying operating system, but there are easier ways to do this if both the caller and the callee are Java programs.
Now, if your jar is gonna change dynamically and you need to update your program according to a new jar, there are mechanisms for reloading its contents, for instance take a look ath this other post.
The JavaDocs for the Process class specifically point out that if you don't capture the output stream of the Process and promptly read it that the process could halt. If this is the case, then you wouldn't see the process that you started run.
I think you have to capture the stream like this :
BufferedReader stdInput = new BufferedReader(new InputStreamReader(runManager.getInputStream()),8*1024);
BufferedReader stdError = new BufferedReader(new InputStreamReader(runManager.getErrorStream()));
// read the output from the command
String s = null;
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
The exec function doesn't automatically lookup into the PATH to start a process, so you have to pass the complete path for the java binary.
You can do that by using the java.home system property, see this answer: ProcessBuilder - Start another process / JVM - HowTo?
No one here seemed to help me, so I went to ask my friend and I had it almost right. It abiously required the string to be an array.
solution:
String[] cmd = {"java", "-jar", currDir};
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e1) {
e1.printStackTrace();
}