Calling Java from Python
Asked Answered
A

9

149

What is the best way to call java from python? (jython and RPC are not an option for me).

I've heard of JCC: http://pypi.python.org/pypi/JCC/1.9 a C++ code generator for calling Java from C++/Python But this requires compiling every possible call; I would prefer another solution.

I've hear about JPype: http://jpype.sourceforge.net/ tutorial: http://www.slideshare.net/onyame/mixing-python-and-java

import jpype 
jpype.startJVM(path to jvm.dll, "-ea") 
javaPackage = jpype.JPackage("JavaPackageName") 
javaClass = javaPackage.JavaClassName 
javaObject = javaClass() 
javaObject.JavaMethodName() 
jpype.shutdownJVM() 

This looks like what I need. However, the last release is from Jan 2009 and I see people failing to compile JPype.

Is JPype a dead project?

Are there any other alternatives?

Allix answered 6/9, 2010 at 15:19 Comment(3)
Could you elaborate on why you think Jython and RPC are not an option for your situation?Strobel
It looks like in the meantime there was a new JPype release: 0.5.4.2 on 2011-07-28Capp
This is a borderline offtopic question partly asking for software recommendations and partly not clear enough (what are the exact requirements for "best way"). Maybe the question could still be improved even today.Deedeeann
D
61

Here is my summary of this problem: 5 Ways of Calling Java from Python

http://baojie.org/blog/2014/06/16/call-java-from-python/ (cached)

Short answer: Jpype works pretty well and is proven in many projects (such as python-boilerpipe), but Pyjnius is faster and simpler than JPype

I have tried Pyjnius/Jnius, JCC, javabridge, Jpype and Py4j.

Py4j is a bit hard to use, as you need to start a gateway, adding another layer of fragility.

Duwalt answered 26/6, 2014 at 19:9 Comment(0)
O
160

You could also use Py4J. There is an example on the frontpage and lots of documentation, but essentially, you just call Java methods from your python code as if they were python methods:

from py4j.java_gateway import JavaGateway
gateway = JavaGateway()                        # connect to the JVM
java_object = gateway.jvm.mypackage.MyClass()  # invoke constructor
other_object = java_object.doThat()
other_object.doThis(1,'abc')
gateway.jvm.java.lang.System.out.println('Hello World!') # call a static method

As opposed to Jython, one part of Py4J runs in the Python VM so it is always "up to date" with the latest version of Python and you can use libraries that do not run well on Jython (e.g., lxml). The other part runs in the Java VM you want to call.

The communication is done through sockets instead of JNI and Py4J has its own protocol (to optimize certain cases, to manage memory, etc.)

Disclaimer: I am the author of Py4J

Orpine answered 25/9, 2010 at 11:0 Comment(7)
Thanks for the link. it looks like an open-source alternative to what djna proposed, CodeMesh. I'll definitively take a look at it. However there is the same problem as in CodeMesh, it requires to start the Java process before, and make sure it is running before using python (see the example in the project's main webpage, ListPrinter.java -> main -> GatewayServer.start()). This is a possible point of failure. I still think that the approach of JPype is excellent; only that it seems a dead project.Allix
@alvas I still maintain Py4J if that's what you meant.Orpine
@Barthelemy, how to go about integrating if the Java code is dependent on a library - opencv in my case?Ucayali
@stack just make sure to add opencv in your classpath and you will be able to access it from Python when you start the GatewayServer.Orpine
Does this work for any package? I tried: s = gateway.jvm.ch.ethz.ssh2.crypto.Base64() bt_out = s.decode(); Here class Base64 has method encode() and decode() and is part of package ch.ethz.ssh2.crypto in my .jar file. I get from py4j.reflection import MethodInvoker ImportError: No module named reflectionSlickenside
@VishalSahu please open a ticket on github with a small code example. I suspect from the error you are getting that the py4j jar is not in your jvm classpath. github.com/bartdag/py4jOrpine
@Orpine We are enjoying Py4J, so thanks for all your hard work. I am however frustrated at being unable to see packages/classes/methods etc. through code completion. Have you found a way round this? #48266427Lizethlizette
D
61

Here is my summary of this problem: 5 Ways of Calling Java from Python

http://baojie.org/blog/2014/06/16/call-java-from-python/ (cached)

Short answer: Jpype works pretty well and is proven in many projects (such as python-boilerpipe), but Pyjnius is faster and simpler than JPype

I have tried Pyjnius/Jnius, JCC, javabridge, Jpype and Py4j.

Py4j is a bit hard to use, as you need to start a gateway, adding another layer of fragility.

Duwalt answered 26/6, 2014 at 19:9 Comment(0)
B
20

Pyjnius docs and Github.

From the github page:

A Python module to access Java classes as Python classes using JNI.

PyJNIus is a "Work In Progress".

Quick overview

>>> from jnius import autoclass
>>> autoclass('java.lang.System').out.println('Hello world') 
Hello world

>>> Stack = autoclass('java.util.Stack')
>>> stack = Stack()
>>> stack.push('hello')
>>> stack.push('world')
>>> print stack.pop()
world
>>> print stack.pop()
hello
Brocklin answered 26/3, 2013 at 0:15 Comment(0)
G
7

If you're in Python 3, there's a fork of JPype called JPype1-py3

pip install JPype1-py3

This works for me on OSX / Python 3.4.3. (You may need to export JAVA_HOME=/Library/Java/JavaVirtualMachines/your-java-version)

from jpype import *
startJVM(getDefaultJVMPath(), "-ea")
java.lang.System.out.println("hello world")
shutdownJVM()
Ghirlandaio answered 5/4, 2015 at 5:27 Comment(0)
L
7

I'm on OSX 10.10.2, and succeeded in using JPype.

Ran into installation problems with Jnius (others have too), Javabridge installed but gave mysterious errors when I tried to use it, PyJ4 has this inconvenience of having to start a Gateway server in Java first, JCC wouldn't install. Finally, JPype ended up working. There's a maintained fork of JPype on Github. It has the major advantages that (a) it installs properly and (b) it can very efficiently convert java arrays to numpy array (np_arr = java_arr[:])

The installation process was:

git clone https://github.com/originell/jpype.git
cd jpype
python setup.py install

And you should be able to import jpype

The following demo worked:

import jpype as jp
jp.startJVM(jp.getDefaultJVMPath(), "-ea")
jp.java.lang.System.out.println("hello world")
jp.shutdownJVM() 

When I tried calling my own java code, I had to first compile (javac ./blah/HelloWorldJPype.java), and I had to change the JVM path from the default (otherwise you'll get inexplicable "class not found" errors). For me, this meant changing the startJVM command to:

jp.startJVM('/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/MacOS/libjli.dylib', "-ea")
c = jp.JClass('blah.HelloWorldJPype')  
# Where my java class file is in ./blah/HelloWorldJPype.class
...
Lantha answered 1/5, 2015 at 12:6 Comment(1)
A small wrapper module to make JPype a bit easier to use is here: github.com/petered/spiking-mlp/blob/master/spiking_mlp/…Lantha
D
5

I've been integrating a lot of stuff into Python lately, including Java. The most robust method I've found is to use IKVM and a C# wrapper.

IKVM has a neat little application that allows you to take any Java JAR, and convert it directly to .Net DLL. It simply translates the JVM bytecode to CLR bytecode. See http://sourceforge.net/p/ikvm/wiki/Ikvmc/ for details.

The converted library behaves just like a native C# library, and you can use it without needing the JVM. You can then create a C# DLL wrapper project, and add a reference to the converted DLL.

You can now create some wrapper stubs that call the methods that you want to expose, and mark those methods as DllEport. See https://mcmap.net/q/160533/-calling-a-c-library-from-python for details.

The wrapper DLL acts just like a native C library, with the exported methods looking just like exported C methods. You can connect to them using ctype as usual.

I've tried it with Python 2.7, but it should work with 3.0 as well. Works on Windows and the Linuxes

If you happen to use C#, then this is probably the best approach to try when integrating almost anything into python.

Denary answered 24/4, 2015 at 20:6 Comment(1)
Uhg... you lost me at C#. I'll not downvote since this is a viable possibility for some cases, but this definitely assumes Windows and a lot of other stuff.Volant
C
3

I'm just beginning to use JPype 0.5.4.2 (july 2011) and it looks like it's working nicely...
I'm on Xubuntu 10.04

Capp answered 27/6, 2012 at 9:40 Comment(0)
A
2

I'm assuming that if you can get from C++ to Java then you are all set. I've seen a product of the kind you mention work well. As it happens the one we used was CodeMesh. I'm not specifically endorsing this vendor, or making any statement about their product's relative quality, but I have seen it work in quite a high volume scenario.

I would say generally that if at all possible I would recommend keeping away from direct integration via JNI if you can. Some simple REST service approach, or queue-based architecture will tend to be simpler to develop and diagnose. You can get quite decent perfomance if you use such decoupled technologies carefully.

Acrimonious answered 6/9, 2010 at 15:35 Comment(3)
RPC (or REST) is not an option for me.Allix
This would require to start the Java process before, and make sure it is running before using python. This is a possible point of failure. The approach of JPype is excellent; only that it seems a dead project.Allix
I'm giving general advice. JNI is a potential minefield.Acrimonious
G
2

Through my own experience trying to run some java code from within python in a manner similar to how python code runs within java code in python, I was unable to find a straightforward methodology.

My solution to my problem was by running this java code as BeanShell scripts by calling the BeanShell interpreter as a shell command from within my python code after editing the java code in a temporary file with the appropriate packages and variables.

If what I am talking about is helpful in any manner, I am glad to help you share more details of my solutions.

Gigantopithecus answered 14/9, 2010 at 7:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.