10

I am using Jython within a Java project.

I have one Java class: myJavaClass.java and one Python class: myPythonClass.py

public class myJavaClass{
    public String myMethod() {
        PythonInterpreter interpreter = new PythonInterpreter();
        //Code to write
    }
 }

The Python file is as follows:

class myPythonClass:
    def abc(self):
        print "calling abc"
        tmpb = {}
        tmpb = {'status' : 'SUCCESS'}
        return tmpb

Now the problem is I want to call the abc() method of my Python file from the myMethod method of my Java file and print the result.

Niklas B.
  • 92,950
  • 18
  • 194
  • 224
Hasti
  • 239
  • 1
  • 3
  • 17
  • 1
    What've you tried? Have you looked at this: http://www.jython.org/archive/21/docs/embedding.html ? – grifaton Feb 21 '12 at 17:20

4 Answers4

16

If I read the docs right, you can just use the eval function:

interpreter.execfile("/path/to/python_file.py");
PyDictionary result = interpreter.eval("myPythonClass().abc()");

Or if you want to get a string:

PyObject str = interpreter.eval("repr(myPythonClass().abc())");
System.out.println(str.toString());

If you want to supply it with some input from Java variables, you can use set beforehand and than use that variable name within your Python code:

interpreter.set("myvariable", Integer(21));
PyObject answer = interpreter.eval("'the answer is: %s' % (2*myvariable)");
System.out.println(answer.toString());
Niklas B.
  • 92,950
  • 18
  • 194
  • 224
  • so do I need to have a line of code such as: interpreter.eval("myPythonClass().abc(myvariable)"); – Hasti Feb 21 '12 at 17:30
  • @ashti: Yeah, that would supply `myvariable` as an argument to the `abc` method of your class. I added another example to demonstrate how to use that newly created variable. – Niklas B. Feb 21 '12 at 17:32
  • Thank you very much for your helpful information. Problem solved! – Hasti Feb 21 '12 at 18:21
  • @hasti: In that case you are invited to accept the answer by clicking at the tick on the left side ;) – Niklas B. Feb 21 '12 at 18:22
  • Sorry but my reputation is low to do so. Also could you help me in converting PyObject to boolean type in java? – Hasti Feb 21 '12 at 20:47
  • @hasti: You don't need rep to accept an answer, please see http://meta.stackexchange.com/a/5235/176476 on how to do so (it's the tick, not the arrows). As for booleans, they are just integers `0/1` in Jython, so you can just use `int t = ((PyInteger) X.eval("True")).asInt()`, for example. – Niklas B. Feb 21 '12 at 20:56
  • I think I am confused. My question was http://stackoverflow.com/questions/9387694/how-to-convert-pyobject-to-java-boolean-type . Is there something I am missing? – Hasti Feb 22 '12 at 01:04
  • @hasti: it's not a boolean, so you can't cast it to a boolean. Just cast it to a `PyInteger` (which it is) and transform that into an `int`, which you can in turn transform into a boolean by checking if it is zero or not. I'll add an answer to that other question. – Niklas B. Feb 22 '12 at 01:05
3

If we need to run a python function that has parameters, and return results, we just need to print this:

import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.util.PythonInterpreter;

public class method {

public static void main(String[] args) {

    PythonInterpreter interpreter = new PythonInterpreter();
    interpreter.execfile("/pathtoyourmodule/somme_x_y.py");
    PyObject str = interpreter.eval("repr(somme(4,5))");
    System.out.println(str.toString());

}

somme is the function in python module somme_x_y.py

def somme(x,y):
   return x+y
1

There isn't any way to do exactly that (that I'm aware of).

You do however have a few options:

1) Execute the python from within java like this:

try {
    String line;
    Process p = Runtime.getRuntime().exec("cmd /c dir");
    BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()));
    BufferedReader bre = new BufferedReader(new InputStreamReader(p.getErrorStream()));
    while ((line = bri.readLine()) != null) {
        System.out.println(line);
    }
    bri.close();
    while ((line = bre.readLine()) != null) {
        System.out.println(line);
    }
    bre.close();
    p.waitFor();
    System.out.println("Done.");
}
catch (Exception err) {
    err.printStackTrace();
}

2) You can maybe use Jython which is "an implementation of the Python programming language written in Java", from there you might have more luck doing what you want.

3) You can make the two applications communicate somehow, with a socket or shared file

Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
0

You can download here Jython 2.7.0 - Standalone Jar.

Then ...

  1. add this to your java path in eclipse......
  2. In the Package Explorer (on the left), right click on your Java project and select Properties.
  3. In the treeview on the left, select Java Build Path.
  4. Select the Libraries tab.
  5. Select Add External JARs...
  6. Browse to your Jython installation (C:\jython2.5.2 for me), and select jython.jar.
  7. Click apply and close.

Then...

Java class (main) //use your won package name and python class dir
-----------------
package javaToPy;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;

public class JPmain {

    @SuppressWarnings("resource")
    public static void main(String[] args) {

    PythonInterpreter interpreter = new PythonInterpreter();

    //set your python program/class dir here
    interpreter.execfile
    ("C:\\Users\\aman0\\Desktop\\ME\\Python\\venv\\PYsum.py");

    PyObject str1 = interpreter.eval("repr(sum(10,50))");
    System.out.println(str1.toString());

    PyObject str2 = interpreter.eval("repr(multi(10,50))");
    System.out.println(str2.toString());


    interpreter.eval("repr(say())");


    interpreter.eval("repr(saySomething('Hello brother'))");

}

}

---------------------------
Python class
------------

def sum(x,y):
    return x+y

def multi(a,b):
    return a*b

def say():
    print("Hello from python")

def saySomething(word):
    print(word)`enter code here`
ZF007
  • 3,708
  • 8
  • 29
  • 48