Three ways to run Python programs from Java

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • kudos
    Recognized Expert New Member
    • Jul 2006
    • 127

    Three ways to run Python programs from Java

    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.

    Code:
    import java.io.*;
    
    class test1{
    public static void main(String a[]){
    try{
    
    String prg = "import sys\nprint int(sys.argv[1])+int(sys.argv[2])\n";
    BufferedWriter out = new BufferedWriter(new FileWriter("test1.py"));
    out.write(prg);
    out.close();
    int number1 = 10;
    int number2 = 32;
    Process p = Runtime.getRuntime().exec("python test1.py "+number1+" "+number2);
    BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
    int ret = new Integer(in.readLine()).intValue();
    System.out.println("value is : "+ret);
    }catch(Exception e){}
    }
    }
    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.

    Code:
    import java.io.*;
    
    class test2{
    public static void main(String a[]){
    try{
    
    String prg = "import sys\nprint int(sys.argv[1])+int(sys.argv[2])\n";
    BufferedWriter out = new BufferedWriter(new FileWriter("test1.py"));
    out.write(prg);
    out.close();
    int number1 = 10;
    int number2 = 32;
    
    ProcessBuilder pb = new ProcessBuilder("python","test1.py",""+number1,""+number2);
    Process p = pb.start();
    
    BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
    int ret = new Integer(in.readLine()).intValue();
    System.out.println("value is : "+ret);
    }catch(Exception e){System.out.println(e);}
    }
    }
    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:



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

    Code:
    import org.python.util.PythonInterpreter; 
    import org.python.core.*; 
    
    class test3{
    public static void main(String a[]){
    
    PythonInterpreter python = new PythonInterpreter();
    
    int number1 = 10;
    int number2 = 32;
    
    python.set("number1", new PyInteger(number1));
    python.set("number2", new PyInteger(number2));
    python.exec("number3 = number1+number2");
    PyObject number3 = python.get("number3");
    System.out.println("val : "+number3.toString());
    }
    }
    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...
  • rspvsanjay
    New Member
    • Sep 2016
    • 21

    #2
    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 ?

    Comment

    • Oralloy
      Recognized Expert Contributor
      • Jun 2010
      • 988

      #3
      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!

      Comment

      • akannac
        New Member
        • Jun 2017
        • 1

        #4
        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

        Comment

        • kozayur
          New Member
          • Oct 2017
          • 1

          #5
          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?

          Comment

          • canaj7
            New Member
            • Jan 2018
            • 2

            #6
            none of these solutions worked.

            Comment

            • canaj7
              New Member
              • Jan 2018
              • 2

              #7
              I get "Exception in thread "main" ImportError: Cannot import site module and its dependencies: No module named site"

              Comment

              • gkbalaajee
                New Member
                • May 2019
                • 1

                #8
                Thank you...

                The solution for first Runtime,Saved my day :)

                Comment

                Working...