====== Calling Java from Python ====== ==== tldr ==== * You want to call a Java library without too much complication, **quick and easy**: **[[calling_java_from_python#jpype | jpype]]**. * You want to create a **compiled egg package** that includes a Java library to be distributed: [[calling_java_from_python#jcc | jcc]] ==== Links ==== * [[https://jpype.readthedocs.io/en/latest/userguide.html#alternatives | Comparison of alternative from the JPyre doc]] * [[https://talvi.net/a-brief-overview-of-python-java-bridges-in-2020.html | A brief overview of python java bridges in 2020 (blog post)]] * ===== Libraries ===== Here is a list of some libraries that can be used to call Java functions and objects from Python. ==== py4j ==== //Py4J enables Python programs running in a Python interpreter to dynamically access Java objects in a Java Virtual Machine. Methods are called as if the Java objects resided in the Python interpreter and Java collections can be accessed through standard Python collection methods. Py4J also enables Java programs to call back Python objects. Py4J is distributed under the BSD license.// === Links === * [[ https://github.com/bartdag/py4j | Github ]] : Contributor: 25, Used by: 5.2k * [[ https://www.py4j.org/ | Website ]] * [[ https://www.py4j.org/contents.html | Documentation ]] === Pros === * A lot of users * Good documentation === Cons === * The gateway approach * Needs to start a java gateway program **Good**: py4j can be a good candidate to allows python **interaction with a long-running java program/server**. === How === py4j do not start the JVM by itself. The JVM needs to be started prior to the execution of the python code and creates an application gateway. import py4j.GatewayServer; public class GatewayApplication { public int called_from_python(int first, int second) { return first + second; } public static void main(String[] args) { GatewayApplication app = new GatewayApplication(); // app is now the gateway.entry_point GatewayServer server = new GatewayServer(app); server.start(); } } The Python code will connect to this running application to interact with the JVM. from py4j.java_gateway import JavaGateway gateway = JavaGateway() # connect to the JVM random = gateway.jvm.java.util.Random() # create a java.util.Random instance number1 = random.nextInt(10) # call the Random.nextInt method number2 = random.nextInt(10) gateway_app = gateway.entry_point # get the GatewwayApplication instance value = gateway_app.called_from_python(number1, number2) # call the addition method print(value) ==== jpype ==== //JPype is a cross-language bridge to allow python programs full access to java class libraries.// //JPype is a Python module to provide full access to Java from within Python. Unlike Jython, JPype does not achieve this by re-implementing Python, but instead by **interfacing both virtual machines at the native level**. This **shared memory-based approach** achieves good computing performance while providing the access to the entirety of CPython and Java libraries. This approach allows direct memory access between the two machines, implementation of Java interfaces in Python, and even use of Java threading.// === Links === * [[ https://github.com/jpype-project/jpype/ | Github ]] : Contributor: 44, Used by: 1.8k * [[ https://jpype.readthedocs.io/en/latest/ | Documentation ]] === Pros === * Easy access to Java library * Easy load of .jar file * Load of users + maintainers * Good documentation === Cons === * Need an independently installed JRE === Example === # Boiler plate stuff to start the module import jpype import jpype.imports from jpype.types import * # Launch the JVM jpype.startJVM(classpath=['jars/database.jar']) # import the Java modules from com.paying.customer import Database db = Database("our_records") with db.connect() as c: c.runQuery() while c.hasRecords(): recor... ==== pyjnius ==== //A Python module to access Java classes as Python classes using the Java Native Interface (JNI).// === Pros === * Developed for/by [[https://kivy.org/ | Kivy ]] === Cons === * Needs Cython * Use reflection to give to Java classes and functions. Could be a lot of work to give access to a whole library. Use of [[https://pyjnius.readthedocs.io/en/stable/api.html#jnius.autoclass | autoclass ]] could limit this problem * I didn't found a way to use/load a .jar! May only give access to the standard Java library * Designed primarily to give access to the standard Java library on Android === Links === * [[ https://github.com/kivy/pyjnius | Github ]] * [[ https://pyjnius.readthedocs.io/en/stable/ | Documentatin ]] ==== JCC ==== //JCC is a C++ code generator that produces a C++ object interface wrapping a Java library via Java's Native Interface (JNI). JCC also generates C++ wrappers that conform to Python's C type system making the instances of Java classes directly available to a Python interpreter.// === Pros === * Allow the creation of an egg that include a small runtime component * Maintained by the apache foundation === Cons === * Could need some refactoring of the code * All java class needed need to be included in the build * More complex than simply importing a module, //i.e.// need to build a library * Compiled solution //i.e.// system dependant * May be not up to date === Links === * [[ https://lucene.apache.org/pylucene/jcc/ | Website ]] * [[ https://pypi.org/project/JCC/ | Pypi ]] ==== python-javabridge ==== // Python wrapper for the Java Native Interface // === Links === * [[ https://github.com/LeeKamentsky/python-javabridge | Github ]] : Contributor: 26, Used by: 162 * [[ http://pythonhosted.org/javabridge/ | Documentation ]] ==== Jython ==== // Jython is a Java implementation of Python. It is not a library to call Java from Python but an implementation of Python in Java. As such, it can interface easily with Java but greatly limits the usefulness of the solution. // **Python 2.7 only** === Links === * [[ https://github.com/jython/jython | Github ]] * [[ https://www.jython.org/ | Website ]]