423,319 Members | 2,562 Online
Bytes IT Community
Submit an Article
Got Smarts?
Share your bits of IT knowledge by writing an article on Bytes.

Three ways to run Python programs from Java

kudos
Expert 100+
P: 126
A week ago, I presented http://bytes.com/topic/python/insigh...hon-together-c. Since then, I realized that perhaps people don't program that much in C. Perhaps people write programs in Java!

Here I present three different options running Python programs from Java; first using the (old) Runtime class, then the ProcessBuilder class and finally embedding Python code in Java, with Jython (a Python interpreter, written in Java!)

Runtime approach

First, let take something that is the old way to do it, the Runtime class.

Expand|Select|Wrap|Line Numbers
  1. import java.io.*;
  2.  
  3. class test1{
  4. public static void main(String a[]){
  5. try{
  6.  
  7. String prg = "import sys\nprint int(sys.argv[1])+int(sys.argv[2])\n";
  8. BufferedWriter out = new BufferedWriter(new FileWriter("test1.py"));
  9. out.write(prg);
  10. out.close();
  11. int number1 = 10;
  12. int number2 = 32;
  13. Process p = Runtime.getRuntime().exec("python test1.py "+number1+" "+number2);
  14. BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
  15. int ret = new Integer(in.readLine()).intValue();
  16. System.out.println("value is : "+ret);
  17. }catch(Exception e){}
  18. }
  19. }
  20.  
We start by making a Java String prg, which contains our Python program, this string is saved on to the file "test1.py". Next, we run the Python interpreter on our system, with the exec method in the Runtime class. We read the output from the output stream returned from the Runtime class, and convert this to an Java int.

I saved the above source code as "test2.java". the I typed the following;

javac test2.java

To execute it:

java test2

Process approach

I think that the Runtime class approach is a bit old. In the newest Java version, the one to use is the ProcessBuilder class. This gives more structure to the arguments.

Expand|Select|Wrap|Line Numbers
  1. import java.io.*;
  2.  
  3. class test2{
  4. public static void main(String a[]){
  5. try{
  6.  
  7. String prg = "import sys\nprint int(sys.argv[1])+int(sys.argv[2])\n";
  8. BufferedWriter out = new BufferedWriter(new FileWriter("test1.py"));
  9. out.write(prg);
  10. out.close();
  11. int number1 = 10;
  12. int number2 = 32;
  13.  
  14. ProcessBuilder pb = new ProcessBuilder("python","test1.py",""+number1,""+number2);
  15. Process p = pb.start();
  16.  
  17. BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
  18. int ret = new Integer(in.readLine()).intValue();
  19. System.out.println("value is : "+ret);
  20. }catch(Exception e){System.out.println(e);}
  21. }
  22. }
  23.  
I saved the above as "test2.java". Then I typed the following;

javac test2.java

To execute it:

java test2

Jython approach

Java is supposed to be platform independent, and to call a native application (like python) isn't very platform independent.

There is a version of Python (Jython) which is written in Java, which allow us to embed Python in our Java programs. As usually, when you are going to use external libraries, one hurdle is to compile and to run it correctly, therefore we go through the process of building and running a simple Java program with Jython.

We start by getting hold of jython jar file:

http://www.jython.org/downloads.html

(When I wrote this, the latest version was : Jython 2.5.3)

I copied jython-2.5.3.jar to the directory where my Java program was going to be. Then I typed in the following program, which do the same as the previous two; take two numbers, sends them to python, which adds them, then python returns it back to our Java program, where the number is outputted to the screen:

Expand|Select|Wrap|Line Numbers
  1. import org.python.util.PythonInterpreter; 
  2. import org.python.core.*; 
  3.  
  4. class test3{
  5. public static void main(String a[]){
  6.  
  7. PythonInterpreter python = new PythonInterpreter();
  8.  
  9. int number1 = 10;
  10. int number2 = 32;
  11.  
  12. python.set("number1", new PyInteger(number1));
  13. python.set("number2", new PyInteger(number2));
  14. python.exec("number3 = number1+number2");
  15. PyObject number3 = python.get("number3");
  16. System.out.println("val : "+number3.toString());
  17. }
  18. }
  19.  
I call this file "test3.java", save it, and do the following to compile it:

javac -classpath jython-2.5.3.jar test3.java

The next step is to try to run it, which I do the following way:

java -classpath jython-2.5.3.jar:. test3

Now, this allows us to use Python from Java, in a platform independent manner. It is kind of slow, in fact it feels like the slowest of the three presented approaches. Still, it's kind of cool, that it is a Python interpreter written in Java...
Jun 15 '13 #1
Share this Article
Share on Google+
6 Comments


P: 21
how do we call python function with one argument by using first or second technique where python code will return string value to java program ?
Sep 23 '16 #2

Oralloy
Expert 100+
P: 983
I would suggest using the class ProcessBuilder to implement a non-trivial solution that includes communication.

Generating Python code on the fly is a cool thought, but is it really valuable? Most problems that I see involve invoking a sub-process that solves a problem (or class of problems); the code is well developed and debugged, so hoisting to Java (or C) is not considered valuable. Or, hoisting is not reasonable, as the problem easily solved in Python, but not in C/C++/Java.

As for the return value, there are a few options:
  1. Capture the printed output of the Python program.
  2. Have the Python program write the desired output to a well-defined file, and just ignore all other output.
  3. Check sub-process return status and act accordingly.

You might want to use an embedded Python interpreter as part of a web page that executes user entered Python in a restricted environment. For example the page may want to forbid access to all file I/O and system interface commands.

Cheers,
Oralloy!
Sep 25 '16 #3

P: 1
this worked perfectly for me, but iím facing another problem, if my python script throws any error like syntax error, the error message is not coming to my java output, i always have to run the script manually and check for any errors. Any idea how to capture that as well
Jun 8 '17 #4

P: 1
Thank you for classifying different methods of calling Python from Java. I wonder if you have some thoughts about the following:

1) If you use Runtime or ProcessBuilder, is there a way to keep python running between calls and submit new commands to the existing process?

2) If you use Jython, is there a way to load C libraries for python?
Oct 5 '17 #5

P: 2
none of these solutions worked.
Jan 24 '18 #6

P: 2
I get "Exception in thread "main" ImportError: Cannot import site module and its dependencies: No module named site"
Jan 24 '18 #7