Виклик Java з Python


123

Який найкращий спосіб викликати java з python? (jython та RPC не є для мене варіантом).

Я чув про JCC: http://pypi.python.org/pypi/JCC/1.9 генератор коду C ++ для виклику Java з C ++ / Python. Але для цього потрібно компілювати всі можливі дзвінки; Я вважаю за краще інше рішення.

Я чув про JPype: http://jpype.sourceforge.net/ підручник: 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() 

Це виглядає як те, що мені потрібно. Однак останній реліз - з січня 2009 року, і я бачу, як люди не можуть скласти JPype.

JPIP проект мертвий?

Чи є інші альтернативи?

З повагою, Девід


3
Не могли б ви детальніше зупинитися на тому, чому ви вважаєте, що Jython та RPC не є варіантом для вашої ситуації?
Натан Девіс

2
Схоже, тим часом з’явився новий реліз JPype: 0.5.4.2 2011-07-28
Joril

Відповіді:


51

Ось мій підсумок цієї проблеми: 5 способів виклику Java з Python

http://baojie.org/blog/2014/06/16/call-java-from-python/ ( кешовано )

Коротка відповідь: Jpype працює досить добре і це підтверджено у багатьох проектах (наприклад, python-kotlepipe), але Pyjnius швидший і простіший ніж JPype

Я спробував Pyjnius / Jnius, JCC, javabridge, Jpype і Py4j.

Py4j трохи складний у використанні, оскільки вам потрібно запустити шлюз, додавши ще один шар крихкості.


135

Ви також можете використовувати Py4J . На прикладі є приклад і велика кількість документації, але, по суті, ви просто викликаєте методи Java з вашого коду python так, ніби вони були методами 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

На відміну від Jython, одна частина Py4J працює у Python VM, тому вона завжди "в курсі" з останньою версією Python, і ви можете використовувати бібліотеки, які не працюють добре на Jython (наприклад, lxml). Інша частина працює у Java VM, яку ви хочете зателефонувати.

Зв'язок здійснюється через сокети замість JNI, а Py4J має власний протокол (для оптимізації певних випадків, для управління пам'яттю тощо)

Відмова: Я є автором Py4J


Дякуємо за посилання це схоже на альтернативу відкритого коду тому, що запропонувала djna, CodeMesh. Я остаточно погляну на це. Однак є та сама проблема, що і в CodeMesh, для цього потрібно запустити процес Java раніше і переконайтеся, що він працює перед використанням python (див. Приклад на головній веб-сторінці проекту, ListPrinter.java -> main -> GatewayServer.start ( )). Це можливий момент невдачі. Я все ще думаю, що підхід JPype є чудовим; лише те, що здається мертвим проектом.
Девід Портабелла

8
@alvas Я все ще підтримую Py4J, якщо це ти мав на увазі.
Вартелемей

@Barthelemy, як іти на інтеграцію, якщо код Java в моєму випадку залежить від бібліотеки - opencv?

1
@stack просто переконайтесь, що ви додали opencv у свій класний шлях, і ви зможете отримати доступ до нього з Python при запуску GatewayServer.
Бартелемі

Це працює для будь-якого пакета? Я спробував: s = gateway.jvm.ch.ethz.ssh2.crypto.Base64() bt_out = s.decode();Тут клас Base64 має метод encode () та decode () і є частиною пакету ch.ethz.ssh2.cryptoв моєму .jar-файлі. Я отримуюfrom py4j.reflection import MethodInvoker ImportError: No module named reflection
Вішал Саху

19

Pyjnius.

Документи: http://pyjnius.readthedocs.org/en/latest/

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

На сторінці github:

Модуль Python для доступу до класів Java як класів Python за допомогою JNI.

PyJNIus - це "Прогрес у стадії".

Швидкий огляд

>>> 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 і мені вдалося використовувати JPype.

Я зіткнувся з проблемами установки Jnius (у інших теж є ), встановив Javabridge, але дав таємничі помилки, коли я намагався ним користуватися, PyJ4 має цю незручність у тому, що спочатку потрібно запустити сервер шлюзу на Java, JCC не встановиться. Нарешті, JPype закінчився. На Github є роздвоєний форк JPype . Він має основні переваги в тому, що (а) він встановлюється належним чином, і (б) він може дуже ефективно перетворювати масиви java в numpy масив (np_arr = java_arr[:] )

Процес встановлення:

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

І ви повинні вміти import jpype

Наступна демонстраційна версія працювала:

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

Коли я спробував зателефонувати на власний код Java, мені спочатку довелося компілювати ( javac ./blah/HelloWorldJPype.java), і мені довелося змінити шлях JVM з типового (інакше ви отримаєте незрозумілі помилки "клас не знайдений"). Для мене це означало зміну команди startJVM на:

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
Пітер

4

Якщо ви перебуваєте в Python 3, є форк JPype під назвою JPype1-py3

pip install JPype1-py3

Це працює для мене на OSX / Python 3.4.3. (Можливо, вам доведеться export JAVA_HOME=/Library/Java/JavaVirtualMachines/your-java-version)

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

4

Останнім часом я інтегрую багато матеріалів у Python, включаючи Java. Найбільш надійний метод, який я знайшов - це використовувати IKVM та обгортку C #.

IKVM має акуратний невеликий додаток, який дозволяє взяти будь-який Java JAR і перетворити його безпосередньо в .Net DLL. Він просто переводить байт-код JVM в байт-код CLR. Докладніше див. На http://sourceforge.net/p/ikvm/wiki/Ikvmc/ .

Перетворена бібліотека поводиться так само, як і рідна бібліотека C #, і ви можете користуватися нею, не потребуючи JVM. Потім можна створити проект обгортки C # DLL і додати посилання на перетворену DLL.

Тепер ви можете створити кілька заглушок обгортки, які викликають методи, які потрібно викрити, і позначити ці методи як DllEport. Докладніше дивіться на https://stackoverflow.com/a/29854281/1977538 .

Обгортка DLL діє так само, як і рідна бібліотека C, причому експортовані методи виглядають так само, як експортовані методи C. Ви можете підключитися до них за допомогою ctype, як зазвичай.

Я спробував це з Python 2.7, але він також повинен працювати з 3.0. Працює під управлінням Windows та Linux

Якщо вам трапляється використовувати C #, то, мабуть, це найкращий підхід, який слід спробувати інтегрувати майже що-небудь у python.


1
Ух ... ти втратив мене на C #. Я не підкажу, оскільки це є можливою можливістю для деяких випадків, але це, безумовно, передбачає Windows та багато іншого.
Джаред

2

Я тільки починаю використовувати JPype 0.5.4.2 (липень 2011 року), і схоже, що він працює добре ...
Я на Xubuntu 10.04


1

Я припускаю, що якщо ви зможете дістатися з C ++ до Java, то все готово. Я бачив продукт такого типу, який ви згадуєте, добре працює. Як це буває, ми використовували CodeMesh . Я спеціально не схвалюю цього постачальника або не заявляю про відносну якість їхнього продукту, але бачив, що це працює за досить високим сценарієм.

Я б загалом сказав, що якщо це можливо, я б рекомендував утримуватися від прямої інтеграції через JNI, якщо можете. Деякі прості підходи до служби REST або архітектура на основі черги, як правило, будуть простішими для розробки та діагностики. Ви можете отримати цілком пристойну ефективність, якщо обережно використовувати такі роз'єднані технології.


RPC (або REST) ​​- це не варіант для мене.
Девід Портабелла

Для цього знадобиться запустити процес Java раніше і переконайтеся, що він працює перед тим, як використовувати python. Це можливий момент невдачі. Підхід JPype відмінний; лише те, що здається мертвим проектом.
Девід Портабелла

Я даю загальні поради. JNI - потенційне мінне поле.
djna

0

Через власний досвід намагаючись запустити якийсь код Java зсередини python ia, подібний до того, як python код працює в коді Java в python, я не зміг знайти методологію прямого руху.

Моє рішення моєї проблеми полягало в тому, що запустив цей код Java в якості скриптів боше, зателефонувавши інтерпретатор бошел як комунальну оболонку з мого коду python після редагування коду Java у тимчасовому файлі з відповідними пакетами та змінними.

Якщо те, про що я говорю, будь-яким чином корисно, я рада допомогти вам поділитися деталями моїх рішень.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.