Python'dan Java'yı Çağırma


123

Python'dan java'yı çağırmanın en iyi yolu nedir? (jython ve RPC benim için bir seçenek değil).

JCC'yi duydum: http://pypi.python.org/pypi/JCC/1.9 Java'yı C ++ / Python'dan çağırmak için bir C ++ kod üreteci Ancak bu, her olası çağrıyı derlemeyi gerektirir; Başka bir çözümü tercih ederim.

JPype hakkında bir şeyler duydum: 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() 

Bu ihtiyacım olan şey gibi görünüyor. Ancak, son sürüm Ocak 2009'dan ve JPype'ı derlemekte başarısız olan insanlar görüyorum.

JPype ölü bir proje mi?

Başka alternatif var mı?

Saygılarımızla, David


3
Neden Jython ve RPC'nin sizin durumunuz için bir seçenek olmadığını düşündüğünüzü açıklayabilir misiniz?
Nathan Davis

2
Bu arada yeni bir JPype sürümü var gibi görünüyor: 2011-07-28 tarihinde
0.5.4.2

Yanıtlar:


51

İşte bu problemin özeti: Python'dan Java'yı Çağırmanın 5 Yolu

http://baojie.org/blog/2014/06/16/call-java-from-python/ ( önbelleğe alınmış )

Kısa cevap: Jpype oldukça iyi çalışıyor ve birçok projede kanıtlanmış (python-boilerpipe gibi), ancak Pyjnius JPype'tan daha hızlı ve daha basit.

Pyjnius / Jnius, JCC, javabridge, Jpype ve Py4j'yi denedim.

Py4j, bir ağ geçidi başlatmanız gerektiğinden, başka bir kırılganlık katmanı eklediğiniz için kullanımı biraz zordur.


135

Py4J'i de kullanabilirsiniz . Ön sayfada bir örnek ve birçok belge var, ancak esasen, Java yöntemlerini python kodunuzdan python yöntemiymiş gibi çağırırsınız:

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

Jython'un aksine, Py4J'nin bir bölümü Python VM'de çalışır, bu nedenle Python'un en son sürümü ile her zaman "günceldir" ve Jython'da iyi çalışmayan kitaplıkları (örneğin, lxml) kullanabilirsiniz. Diğer kısım, aramak istediğiniz Java VM'de çalışır.

İletişim JNI yerine soketler aracılığıyla yapılır ve Py4J'nin kendi protokolü vardır (belirli durumları optimize etmek, belleği yönetmek vb. İçin)

Feragatname: Py4J'nin yazarıyım


Bağlantı için teşekkürler. djna'nın önerdiği CodeMesh'e açık kaynaklı bir alternatif gibi görünüyor. Kesinlikle bir göz atacağım. Ancak CodeMesh'teki ile aynı sorun var, Java sürecini daha önce başlatmayı ve python kullanmadan önce çalıştığından emin olmayı gerektirir (projenin ana web sayfasındaki örneğe bakın, ListPrinter.java -> main -> GatewayServer.start ( )). Bu olası bir başarısızlık noktasıdır. Hala JPype yaklaşımının mükemmel olduğunu düşünüyorum; sadece ölü bir proje gibi görünmesi.
David Portabella

8
@alvas Demek istediğin buysa, Py4J'i hala sürdürüyorum.
Barthelemy

@Barthelemy, Java kodu bir kütüphaneye bağlıysa entegrasyona nasıl gidebilirim - benim durumumda opencv?

1
@stack, sınıf yolunuza opencv eklediğinizden emin olun ve GatewayServer'ı başlattığınızda Python'dan ona erişebileceksiniz.
Barthelemy

Bu herhangi bir paket için çalışıyor mu? Denedim: s = gateway.jvm.ch.ethz.ssh2.crypto.Base64() bt_out = s.decode();Burada Base64 sınıfı encode () ve decode () yöntemine sahip ve ch.ethz.ssh2.crypto.jar dosyamdaki paketin bir parçası . Anlıyorumfrom py4j.reflection import MethodInvoker ImportError: No module named reflection
Vishal Sahu

19

Pyjnius.

Dokümanlar: http://pyjnius.readthedocs.org/en/latest/

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

Github sayfasından:

Java sınıflarına JNI kullanarak Python sınıfları olarak erişmek için bir Python modülü.

PyJNIus bir "Devam Eden Çalışma" dır.

Hızlı genel bakış

>>> 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

5

OSX 10.10.2 kullanıyorum ve JPype kullanmayı başardım.

Jnius ile yükleme problemleriyle karşılaştım ( diğerlerinde de var ), Javabridge yüklendi ancak kullanmaya çalıştığımda gizemli hatalar verdi, PyJ4'ün bu rahatsızlığı, önce Java'da bir Ağ Geçidi sunucusu başlatmak zorunda kaldı, JCC yüklenmedi. Sonunda, JPype çalışmaya başladı. Bir var Jpype ait tutulan çatal Github. (A) düzgün bir şekilde kurması ve (b) java dizilerini çok verimli bir şekilde numpy dizisine ( np_arr = java_arr[:]) dönüştürebilmesinin başlıca avantajları vardır.

Kurulum süreci şöyleydi:

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

Ve yapabilmelisin import jpype

Aşağıdaki demo çalıştı:

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

Kendi java kodumu çağırmayı denediğimde, önce derlemek ( javac ./blah/HelloWorldJPype.java) ve JVM yolunu varsayılandan değiştirmek zorunda kaldım (aksi takdirde açıklanamaz "sınıf bulunamadı" hataları alırsınız). Benim için bu, startJVM komutunu şu şekilde değiştirmek anlamına geliyordu:

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
...

JPype kullanımını biraz daha kolaylaştırmak için küçük bir sarmalayıcı modülü burada: github.com/petered/spiking-mlp/blob/master/spiking_mlp/…
Peter

4

Python 3'teyseniz, JPype1-py3 adında bir JPype çatalı var

pip install JPype1-py3

Bu benim için OSX / Python 3.4.3'te çalışıyor. (İhtiyacınız olabilir export JAVA_HOME=/Library/Java/JavaVirtualMachines/your-java-version)

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

4

Son zamanlarda Java da dahil olmak üzere birçok şeyi Python'a entegre ediyorum. Bulduğum en sağlam yöntem IKVM ve C # sarıcı kullanmaktır.

IKVM, herhangi bir Java JAR'ı almanıza ve onu doğrudan .Net DLL'ye dönüştürmenize izin veren küçük, temiz bir uygulamaya sahiptir. JVM bayt kodunu CLR bayt koduna çevirir. Ayrıntılar için http://sourceforge.net/p/ikvm/wiki/Ikvmc/ adresine bakın.

Dönüştürülen kütüphane, yerel bir C # kütüphanesi gibi davranır ve onu JVM'ye ihtiyaç duymadan kullanabilirsiniz. Daha sonra bir C # DLL sarmalayıcı projesi oluşturabilir ve dönüştürülen DLL'ye bir başvuru ekleyebilirsiniz.

Artık ortaya çıkarmak istediğiniz yöntemleri çağıran ve bu yöntemleri DllEport olarak işaretleyen bazı sarmalayıcı saplamalar oluşturabilirsiniz. Ayrıntılar için https://stackoverflow.com/a/29854281/1977538 adresine bakın.

Sarmalayıcı DLL, dışa aktarılan yöntemler dışa aktarılan C yöntemlerine benzeyen yerel bir C kitaplığı gibi davranır. Her zamanki gibi ctype kullanarak onlara bağlanabilirsiniz.

Python 2.7 ile denedim ama 3.0 ile de çalışmalı. Windows ve Linux'larda çalışır

Eğer C # kullanıyorsanız, bu muhtemelen neredeyse her şeyi python'a entegre ederken denenecek en iyi yaklaşımdır.


1
Uhg ... beni C # 'da kaybettin. Bazı durumlarda bu geçerli bir olasılık olduğundan olumsuz oy kullanmayacağım, ancak bu kesinlikle Windows'u ve diğer birçok şeyi varsayar.
Jared

2

JPype 0.5.4.2'yi (temmuz 2011) yeni kullanmaya başlıyorum ve güzel çalışıyor gibi görünüyor ...
Xubuntu 10.04'teyim


1

C ++ 'dan Java'ya geçebilirseniz, o zaman hepinizin hazır olduğunu varsayıyorum. Bahsettiğiniz türden bir ürünün iyi çalıştığını gördüm. Olduğu gibi kullandığımız CodeMesh idi . Bu satıcıyı özel olarak desteklemiyorum veya ürünlerinin göreceli kalitesi hakkında herhangi bir açıklama yapmıyorum, ancak oldukça yüksek hacimli bir senaryoda çalıştığını gördüm.

Genel olarak şunu söyleyebilirim, eğer mümkünse, mümkünse JNI aracılığıyla doğrudan entegrasyondan uzak durmanızı tavsiye ederim. Bazı basit REST hizmeti yaklaşımı veya kuyruk tabanlı mimarinin geliştirilmesi ve teşhisi daha kolay olacaktır. Bu tür ayrıştırılmış teknolojileri dikkatli kullanırsanız oldukça iyi bir performans elde edebilirsiniz.


RPC (veya REST) ​​benim için bir seçenek değil.
David Portabella

Bu, Java sürecini daha önce başlatmayı ve python'u kullanmadan önce çalıştığından emin olmayı gerektirir. Bu olası bir başarısızlık noktasıdır. JPype yaklaşımı mükemmel; sadece ölü bir proje gibi görünmesi.
David Portabella

Genel tavsiye veriyorum. JNI, potansiyel bir mayın tarlasıdır.
djna

0

Python'daki java kodu içinde python kodunun nasıl çalıştığına benzer bir şekilde python içinden bazı java kodunu çalıştırmaya çalıştığım kendi deneyimlerime dayanarak, basit bir metodoloji bulamadım.

Benim sorunuma çözümüm, java kodunu geçici bir dosyada uygun paketler ve değişkenlerle düzenledikten sonra fasulyehell yorumlayıcısını python kodumun içinden bir kabuk komutu olarak çağırarak bu java kodunu Beanhell komut dosyaları olarak çalıştırmaktı.

Bahsettiğim şey herhangi bir şekilde yardımcı oluyorsa, çözümlerim hakkında daha fazla ayrıntı paylaşmanıza yardımcı olmaktan memnuniyet duyarım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.