This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Calling Java app with “subprocess” from Python and reading the Java app output
Basically what I am looking for is, I want to interact with java program while its running using python so I can access its output and pass input to it.
I have managed to run a Java program using python. I want to know can i access the outputs of java program in my python program.
For example.
In java program: System.out.println("Enter no.");
In python i should be able to get "Enter no" as string and also pass value to java program from python.a
What I managed to do till no :
Python program :
import sys
import os.path,subprocess
def compile_java(java_file):
subprocess.check_call(['javac', java_file])
def execute_java(java_file):
java_class,ext = os.path.splitext(java_file)
cmd = ['java', java_class]
subprocess.call(cmd, shell=False)
def run_java(java_file):
compile_java(java_file)
execute_java(java_file)
Java Program :
import java.io.*;
import java.util.*;
class Hi
{
public static void main(String args[])throws IOException
{
Scanner t=new Scanner(System.in);
System.out.println("Enter any integer");
int str1=t.nextInt();
System.out.println("You entered"+str1);
}
}
Thanx :)
If all you need is to get the output from a non-interactive execution of your Java program, use subprocess.check_output instead of subprocess.call.
http://docs.python.org/library/subprocess.html
You need Python 2.7 or newer for check_output to be available.
If you need to interact with the Java program, you can do so using Popen.communicate, where you can read the process's output and send stuff to its input using file descriptors.
You can also use the pexpect python library to automate this kind of interaction, pexpect abstracts a lot of the legwork involved in using Popen.communicate.
Note that these techniques apply for any kind of executable you need your Python program to interact with, not just Java; as long as it uses stdin and stdout, using these calls should work for you.
The easiest way would be to use Jython, which is a complete Python implementation that runs in the JVM, and can interact with native Java code. But if you want to use CPython, and generally continue down the path you've sketched out above, you'll want to create a live Python Popen object that you can interact with. For example:
import sys
import os.path,subprocess
def compile_java(java_file):
subprocess.check_call(['javac', java_file])
def execute_java(java_file):
java_class,ext = os.path.splitext(java_file)
cmd = ['java', java_class]
return subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
def run_java(java_file):
compile_java(java_file)
process = execute_java(java_file)
for i in range(10):
process.stdin.write(str(i) + "\n")
Related
I have created the following Java class and saved it as Test.java, then compiled into Test.class on the command line using javac Test.java:
public class Test {
public Test() {
}
public double power(double number) {
System.out.println("calculating...");
return number * number;
}
}
Furthermore, I have created the following R script and saved it as test.R:
library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)
When I execute it, for example using R CMD BATCH test.R on the command line, I get the following output, which is what I want:
calculating...
[1] 9
However, when I wrap this script in a Markdown document and compile it using knitr, I lose the message that is printed about the calculation taking place. For example, I save the following script in test.Rmd and compile it using RStudio:
```{r echo=TRUE, warning=TRUE, results='show', message=TRUE}
library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)
```
This only returns the following output, without the message:
## [1] 9
I read somewhere that the reason is that System.out.println in Java writes to stdout, and whether this is shown in the R console or not depends on the interpreter. For example, the output is shown on Unix systems but not on Windows or in knitr.
My questions:
Is the above interpretation correct?
How can I reliably capture or display the output of System.out.println in R, irrespective of operating system or interpreter?
If that's not possible, what is a better way of designing status messages about the current calculations and progress in Java, such that R can display these messages?
Thanks!
I'll take a stab at answering my own question... Looks like the RJava folks actually offer a built-in solution (thanks Simon Urbanek if you read this). On the side of the Java code, there is the LGPL-licensed JRI.jar, which is delivered with rJava (look at the jri sub-directory in the rJava package directory in your local R library path) and which can be copied/extracted into the Java library path. It's only 82kb, so fairly light-weight.
JRI offers a replacement of the default print stream in Java. Essentially, you redirect the system output into an RConsoleOutputStream provided by JRI. The code in my question above can be modified as follows to print to the R console instead of stdout.
import java.io.PrintStream;
import org.rosuda.JRI.RConsoleOutputStream;
import org.rosuda.JRI.Rengine;
public class Test {
public Test() {
Rengine r = new Rengine();
RConsoleOutputStream rs = new RConsoleOutputStream(r, 0);
System.setOut(new PrintStream(rs));
}
public double power(double number) {
System.out.println("calculating...");
return number * number;
}
}
I'm building a Python UI using Tkinter. For the needs of the program, I've to connect Python with Java to do some stuff, so I'm using a simple Jython script as a linker. I cant use Tkinter with Jython because it's not supported.
Python (ui.py) -> Jython (linker.py) -> Java (compiled in jars)
To call the Jython function in Python I use subprocess as follows:
ui.py:
cmd = 'jython linker.py"'
my_env = os.environ
my_env["JYTHONPATH"] = tons_of_jars
subprocess.Popen(cmd, shell=True, env=my_env)
Then, in the Jython file, linker.py, I import the Java classes already added on the JYTHONPATH, and I create an object with the name m and call to some functions of the Java class.
linker.py:
import handler.handler
m = handler.handler(foo, moo, bar)
m.schedule(moo)
m.getFullCalendar()
m.printgantt()
The thing is that I've created a m object, that will be destroyed after the execution of jython linker.py ends.
So the question is: Is possible to save that m object somewhere so I can call it from ui.py whenever I want? If it's not possible, is there any other way to do this?
Thanks in advance.
I finally solved it by using ObjectOutputStream.
from java import io
def saveObject(x, fname="object.bin"):
outs = io.ObjectOutputStream(io.FileOutputStream(fname))
outs.writeObject(x)
outs.close()
def loadObject(fname="object.bin"):
ins = io.ObjectInputStream(io.FileInputStream(fname))
x=ins.readObject()
ins.close()
return x
This question already has answers here:
Calling Java app with "subprocess" from Python and reading the Java app output
(2 answers)
Closed 8 years ago.
I am running a Python script that runs a Java class that requires nondeterministic user input:
import sys
import subprocess
from subprocess import Popen, PIPE
p = Popen("java myclass", shell=True, stdout=subprocess.PIPE)
while True:
inline = p.stdout.readline()
if not inline:
break
sys.stdout.write(inline)
sys.stdout.flush()
When output is displayed using System.out.print(), the output is displayed properly. However, when a prompt for user input is printed with System.out.print(), the output is not displayed. I tried switching p.stdout.readline() to p.stdout.read(), but then no output is displayed. Is there a way to display an input prompt that does not have a carriage return?
EDIT
For example, if the Java class contains the following:
System.out.println("Message 1);
System.out.println("Message 2);
System.out.print("Enter a number:")
Running the pure Java code would display all 3 lines.
The code running through Python would only display the following:
Message 1
Message 2
p1 = subprocess.Popen(["/usr/bin/java", "MyClass"], stdout=subprocess.PIPE)
print p1.stdout.read()
I am calling a Python script from my Java code. This is the code :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class JavaRunCommand {
public static void main(String args[]) throws IOException {
// set up the command and parameter
String pythonScriptPath = "my-path";
String[] cmd = new String[2];
cmd[0] = "python2.6";
cmd[1] = pythonScriptPath;
// create runtime to execute external command
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(cmd);
// retrieve output from python script
BufferedReader bfr = new BufferedReader(new InputStreamReader(
pr.getInputStream()));
String line = "";
while ((line = bfr.readLine()) != null) {
// display each output line form python script
System.out.println(line);
}
}
}
python.py which works
import os
from stat import *
c = 5
print c
python.py which does not works
import MySQLdb
import os
from stat import *
c = 5
print c
# some database code down
So, I am at a critical stage where I have a deadline for my startup and I have to show my MVP project to the client and I was thinking of calling Python script like this. It works when I am printing anything without dB connection and MySQLdb library. But when I include them, it does not run the python script. Whats wrong here. Isnt it suppose to run the process handling all the inputs. I have MySQLdb installed and the script runs without the java code.
I know this is not the best way to solve the issue. But to show something to the client I need this thing working. Any suggestions ?
So, I discovered that the issue was with the arguments that I was passing in Java to run the python program.
The first argument was - python 2.6 but it should have rather been just python not some version number because there was compatibility issue with MySQLdB and python.
I finally decided to use MySQL Python connector instead of MySQLdB in python code. It worked like charm and the problems got solved !
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How to run a python script from java?
I am running a Python script using Jython and got this error:
Exception in thread "main" Traceback (innermost last): File "C:\Facebook\LoginPython\Facebook.py", line 5, in ? ImportError: no module named cookielib
Why doesn't this work?
A little bit more about using Jython - had my share of problems with that as well. Note that this may not be the best way to do it, but it works fine for me.
I assume you want to call a function foo in module bar from your Java code that takes a string argument and returns a string:
PythonInterpreter interpreter = new PythonInterpreter();
// Append directory containing module to python search path and import it
interpreter.exec("import sys\n" + "sys.path.append(pathToModule)\n" +
"from bar import foo");
PyObject meth = interpreter.get("foo");
PyObject result = meth.__call__(new PyString("Test!"));
String real_result = (String) result.__tojava__(String.class);
The sys.path.append() part is only necessary if your module isn't part of the Python search path by default, which may very well be the problem if you get Import or Module not find errors.
Also you need to cast the objects between the java and python versions, you'll need to look that up if necessary, so far I only needed primitive types that were easy to cast, not sure if it's as easy for arbitrary java objects.
Use Jython to run Python on the JVM. Use PyDev to develop with Python (or Jython) on Eclipse.