Memanggil Java dari Python

123

Apa cara terbaik untuk memanggil java dari python? (jython dan RPC bukanlah pilihan bagi saya).

Saya pernah mendengar tentang JCC: http://pypi.python.org/pypi/JCC/1.9 generator kode C ++ untuk memanggil Java dari C ++ / Python Tapi ini membutuhkan kompilasi setiap panggilan yang mungkin; Saya lebih suka solusi lain.

Saya pernah mendengar tentang 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() 

Ini terlihat seperti yang saya butuhkan. Namun, rilis terakhir adalah dari Jan 2009 dan saya melihat orang-orang gagal untuk mengkompilasi JPype.

Apakah JPype proyek mati?

Apakah ada alternatif lain?

Salam, David

David Portabella
sumber
3
Bisakah Anda menjelaskan mengapa menurut Anda Jython dan RPC bukanlah pilihan untuk situasi Anda?
Nathan Davis
2
Sepertinya sementara itu ada rilis JPype baru: 0.5.4.2 pada 2011-07-28
Joril

Jawaban:

51

Berikut adalah ringkasan saya dari masalah ini: 5 Cara Memanggil Java dari Python

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

Jawaban singkat: Jpype bekerja dengan cukup baik dan terbukti di banyak proyek (seperti python-boilerpipe), tetapi Pyjnius lebih cepat dan lebih sederhana daripada JPype

Saya telah mencoba Pyjnius / Jnius, JCC, javabridge, Jpype dan Py4j.

Py4j agak sulit digunakan, karena Anda perlu memulai gateway, menambahkan lapisan kerapuhan lainnya.

Jie Bao
sumber
135

Anda juga bisa menggunakan Py4J . Ada contoh di halaman depan dan banyak dokumentasi, tetapi pada dasarnya, Anda cukup memanggil metode Java dari kode python Anda seolah-olah itu adalah metode python:

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

Berbeda dengan Jython, satu bagian dari Py4J berjalan di VM Python sehingga selalu "mutakhir" dengan versi terbaru Python dan Anda dapat menggunakan pustaka yang tidak berjalan dengan baik di Jython (misalnya, lxml). Bagian lainnya berjalan di VM Java yang ingin Anda panggil.

Komunikasi dilakukan melalui soket, bukan JNI dan Py4J memiliki protokolnya sendiri (untuk mengoptimalkan kasus tertentu, untuk mengelola memori, dll.)

Penafian: Saya adalah penulis Py4J

Barthelemy
sumber
Terima kasih untuk tautannya. sepertinya alternatif open-source untuk apa yang diusulkan djna, CodeMesh. Saya pasti akan melihatnya. Namun ada masalah yang sama seperti di CodeMesh, yang mengharuskan untuk memulai proses Java sebelumnya, dan memastikannya berjalan sebelum menggunakan python (lihat contoh di halaman web utama proyek, ListPrinter.java -> main -> GatewayServer.start ( )). Ini adalah titik kegagalan yang mungkin. Saya masih berpikir bahwa pendekatan JPype sangat bagus; hanya itu tampaknya proyek mati.
David Portabella
8
@alvas saya masih mempertahankan Py4J jika itu yang Anda maksud.
Barthelemy
@Barthelemy, bagaimana cara mengintegrasikan jika kode Java bergantung pada perpustakaan - opencv dalam kasus saya?
1
@stack pastikan untuk menambahkan opencv di classpath Anda dan Anda akan dapat mengaksesnya dari Python saat Anda memulai GatewayServer.
Barthelemy
Apakah ini berfungsi untuk paket apa pun? Saya mencoba: s = gateway.jvm.ch.ethz.ssh2.crypto.Base64() bt_out = s.decode();Di sini kelas Base64 memiliki metode encode () dan decode () dan merupakan bagian dari paket ch.ethz.ssh2.cryptodalam file .jar saya. Saya mendapatkanfrom py4j.reflection import MethodInvoker ImportError: No module named reflection
Vishal Sahu
19

Pyjnius.

Docs: http://pyjnius.readthedocs.org/en/latest/

Github: https://github.com/kivy/pyjnius

Dari halaman github:

Modul Python untuk mengakses kelas Java sebagai kelas Python menggunakan JNI.

PyJNIus adalah "Work In Progress".

Gambaran singkat

>>> 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
gdw2.dll
sumber
5

Saya menggunakan OSX 10.10.2, dan berhasil menggunakan JPype.

Mengalami masalah instalasi dengan Jnius ( orang lain juga ), Javabridge diinstal tetapi memberikan kesalahan misterius ketika saya mencoba menggunakannya, PyJ4 mengalami ketidaknyamanan ini karena harus memulai server Gateway di Java terlebih dahulu, JCC tidak akan menginstal. Akhirnya, JPype akhirnya berhasil. Ada garpu JPype yang dipertahankan di Github. Ini memiliki keuntungan utama yaitu (a) diinstal dengan benar dan (b) dapat dengan sangat efisien mengonversi array java menjadi numpy array ( np_arr = java_arr[:])

Proses instalasi adalah:

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

Dan Anda harus bisa import jpype

Demo berikut berhasil:

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

Ketika saya mencoba memanggil kode java saya sendiri, saya harus terlebih dahulu mengkompilasi ( javac ./blah/HelloWorldJPype.java), dan saya harus mengubah jalur JVM dari default (jika tidak, Anda akan mendapatkan kesalahan "kelas tidak ditemukan" yang tidak dapat dijelaskan). Bagi saya, ini berarti mengubah perintah startJVM menjadi:

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
...
Peter
sumber
Modul pembungkus kecil untuk membuat JPype sedikit lebih mudah digunakan ada di sini: github.com/petered/spiking-mlp/blob/master/spiking_mlp/…
Peter
4

Jika Anda menggunakan Python 3, ada percabangan JPype yang disebut JPype1-py3

pip install JPype1-py3

Ini berfungsi untuk saya di OSX / Python 3.4.3. (Anda mungkin perlu export JAVA_HOME=/Library/Java/JavaVirtualMachines/your-java-version)

from jpype import *
startJVM(getDefaultJVMPath(), "-ea")
java.lang.System.out.println("hello world")
shutdownJVM()
k107
sumber
4

Saya telah mengintegrasikan banyak hal ke Python belakangan ini, termasuk Java. Metode paling kuat yang saya temukan adalah menggunakan IKVM dan pembungkus C #.

IKVM memiliki aplikasi kecil yang rapi yang memungkinkan Anda untuk mengambil Java JAR apa pun, dan mengubahnya langsung ke .Net DLL. Ini hanya menerjemahkan bytecode JVM ke bytecode CLR. Lihat http://sourceforge.net/p/ikvm/wiki/Ikvmc/ untuk detailnya.

Pustaka yang dikonversi berperilaku seperti pustaka C # asli, dan Anda dapat menggunakannya tanpa memerlukan JVM. Anda kemudian dapat membuat proyek pembungkus C # DLL, dan menambahkan referensi ke DLL yang dikonversi.

Sekarang Anda dapat membuat beberapa rintisan pembungkus yang memanggil metode yang ingin Anda tampilkan, dan menandai metode tersebut sebagai DllEport. Lihat https://stackoverflow.com/a/29854281/1977538 untuk detailnya.

DLL pembungkus bertindak seperti pustaka C asli, dengan metode yang diekspor tampak seperti metode C yang diekspor. Anda dapat terhubung dengan mereka menggunakan ctype seperti biasa.

Saya sudah mencobanya dengan Python 2.7, tetapi seharusnya berfungsi dengan 3.0 juga. Bekerja di Windows dan Linux

Jika Anda kebetulan menggunakan C #, maka ini mungkin pendekatan terbaik untuk dicoba ketika mengintegrasikan hampir semua hal ke dalam python.

Rob Deary
sumber
1
Uhg ... Anda kehilangan saya di C #. Saya tidak akan menurunkan suara karena ini adalah kemungkinan yang layak untuk beberapa kasus, tetapi ini pasti mengasumsikan Windows dan banyak hal lainnya.
Jared
2

Saya baru mulai menggunakan JPype 0.5.4.2 (Juli 2011) dan sepertinya berfungsi dengan baik ...
Saya menggunakan Xubuntu 10.04

Joril
sumber
1

Saya berasumsi bahwa jika Anda bisa berpindah dari C ++ ke Java maka Anda sudah siap. Saya telah melihat produk dari jenis yang Anda sebutkan bekerja dengan baik. Kebetulan yang kami gunakan adalah CodeMesh . Saya tidak secara khusus mendukung vendor ini, atau membuat pernyataan apa pun tentang kualitas relatif produk mereka, tetapi saya telah melihatnya berfungsi dalam skenario volume yang cukup tinggi.

Saya akan mengatakan secara umum bahwa jika memungkinkan, saya akan merekomendasikan untuk tidak melakukan integrasi langsung melalui JNI jika Anda bisa. Beberapa pendekatan layanan REST sederhana, atau arsitektur berbasis antrian akan cenderung lebih sederhana untuk dikembangkan dan didiagnosis. Anda bisa mendapatkan kinerja yang cukup baik jika Anda menggunakan teknologi yang dipisahkan dengan hati-hati.

djna
sumber
RPC (atau REST) ​​bukanlah pilihan bagi saya.
David Portabella
Ini akan membutuhkan untuk memulai proses Java sebelumnya, dan memastikan itu berjalan sebelum menggunakan python. Ini adalah titik kegagalan yang mungkin. Pendekatan JPype sangat bagus; hanya itu tampaknya proyek mati.
David Portabella
Saya memberikan nasihat umum. JNI adalah ladang ranjau yang potensial.
djna
0

Melalui pengalaman saya sendiri mencoba menjalankan beberapa kode java dari dalam python ia dengan cara yang mirip dengan bagaimana kode python berjalan dalam kode java di python, saya tidak dapat menemukan metodologi langsung.

Solusi saya untuk masalah saya adalah dengan menjalankan kode java ini sebagai skrip beanhell dengan memanggil juru bahasa beanshell sebagai shell commnad dari dalam kode python saya setelah mengedit kode java dalam file sementara dengan paket dan variabel yang sesuai.

Jika apa yang saya bicarakan bermanfaat dalam hal apa pun, saya senang membantu Anda membagikan lebih banyak detail tentang solusi saya.

alaa teduh
sumber