10

I've recently discovered py4j and was able to call static java methods from python. Now I want to call python methods from java. I couldn't find much documentation so this is the last place I can think of that might tell me if it's possible, and how.

Limnic
  • 1,826
  • 1
  • 20
  • 45
  • Possible duplicate: http://stackoverflow.com/questions/14450173/send-a-python-object-to-java-using-py4j?rq=1 – Barthelemy Apr 19 '14 at 12:45

1 Answers1

12

You can call a Python method from Java by implementing a Java interface on the python side.

The steps are:

  1. Create an interface in Java, e.g., py4j.examples.Operator
  2. In Python, create a class and inside the class, create a Java class with an "implements" field.
  3. In Python, instantiate a gateway with start_callback_server=True, e.g., gateway = JavaGateway(start_callback_server=True)
  4. In Python, instantiate the class implementing a Java interface and send it to the Java side.
  5. In Java, call the interface.

Example adapted from the Py4J documentation:

Java code:

// File 1
package py4j.examples;

public interface Operator {
        public int doOperation(int i, int j);
        public int doOperation(int i, int j, int k);
}

// File 2
package py4j.examples;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import py4j.GatewayServer;

public class OperatorExample {

    // To prevent integer overflow
    private final static int MAX = 1000;

    public List<Integer> randomBinaryOperator(Operator op) {
        Random random = new Random();
        List<Integer> numbers = new ArrayList<Integer>();
        numbers.add(random.nextInt(MAX));
        numbers.add(random.nextInt(MAX));
        numbers.add(op.doOperation(numbers.get(0), numbers.get(1)));
        return numbers;
    }
}

Python code:

from py4j.java_gateway import JavaGateway

class Addition(object):
    def doOperation(self, i, j, k = None):
        if k == None:
            return i + j
        else:
            return i + j + k

    class Java:
        implements = ['py4j.examples.Operator']

if __name__ == '__main__':
    gateway = JavaGateway(start_callback_server=True)
    operator = Addition()
    operator_example = gateway.jvm.py4j.examples.OperatorExample()

    # "Sends" python object to the Java side.
    numbers = operator_example.randomBinaryOperator(operator) 
Barthelemy
  • 8,277
  • 6
  • 33
  • 36
  • Great example. Could you tell how this can be achieved with py4j 0.8.2.1 – user3451476 Jul 11 '16 at 20:28
  • can we call python function given `.py` file without requiring to modify python script. Using Jython PythonInterpreter, we can [straight a way call function defined in the python file](http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html#utilizing-pythoninterpreter). Is something similar possible with py4j? – Mahesha999 Sep 09 '16 at 10:18
  • @Mahesha999 no, it's not possible to just interpret straight python code from Java, but you might be interested in Eclipse EASE which provides an environment where this is somehow possible. – Barthelemy Sep 09 '16 at 14:29
  • 1
    hey, thanks for the nice example. i need to call python from java side too but the python function should return an huge array of float values. how can i do that? – white91wolf Oct 31 '19 at 10:24
  • Here, the python code is 'sending' object to Java. If I want control flow such that Java code can call python function, when required. Is it possible with py4j ? – Sid May 18 '20 at 14:44