Вызов 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.

JPype - мертвый проект?

Есть ли другие альтернативы?

С уважением, Дэвид

Дэвид Портабелла
источник
3
Не могли бы вы пояснить, почему вы думаете, что Jython и RPC не подходят для вашей ситуации?
Натан Дэвис,
2
Похоже, что тем временем вышла новая версия JPype: 0.5.4.2 28
июля 2011 г.

Ответы:

51

Вот мое краткое изложение этой проблемы: 5 способов вызова Java из Python

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

Краткий ответ: Jpype работает довольно хорошо и доказал свою эффективность во многих проектах (например, python-котелпайп), но 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, поэтому она всегда «обновлена» до последней версии Python, и вы можете использовать библиотеки, которые плохо работают на Jython (например, lxml). Другая часть работает в виртуальной машине Java, которую вы хотите вызвать.

Связь осуществляется через сокеты вместо JNI, а Py4J имеет собственный протокол (для оптимизации определенных случаев, для управления памятью и т. Д.)

Отказ от ответственности: я являюсь автором Py4J

Бартелеми
источник
Спасибо за ссылку. он выглядит как альтернатива с открытым исходным кодом CodeMesh, предложенная djna. Я обязательно посмотрю на это. Однако существует та же проблема, что и в 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
gdw2
источник
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-код, мне пришлось сначала выполнить compile ( 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 находится здесь: github.com/petered/spiking-mlp/blob/master/spiking_mlp/…
Питер,
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()
K107
источник
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

Joril
источник
1

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

В целом я бы сказал, что по возможности я бы порекомендовал воздержаться от прямой интеграции через JNI, если это возможно. Некоторые простые подходы к службам REST или архитектуру на основе очередей будут проще в разработке и диагностике. Вы можете получить вполне приличную производительность, если будете осторожно использовать такие изолированные технологии.

DJNA
источник
RPC (или REST) ​​для меня не вариант.
Дэвид Портабелла
Для этого потребуется запустить процесс Java раньше и убедиться, что он запущен, прежде чем использовать python. Это возможная точка отказа. Подход JPype превосходен; только то, что кажется мертвым проектом.
Дэвид Портабелла
Даю общий совет. JNI - потенциальное минное поле.
djna
0

Благодаря моему собственному опыту, пытаясь запустить некоторый java-код изнутри python ia способом, похожим на то, как python-код работает внутри java-кода в python, мне не удалось найти прямую методологию.

Мое решение моей проблемы заключалось в запуске этого java-кода в виде сценариев beanshell путем вызова интерпретатора beanshell в качестве команды оболочки из моего кода python после редактирования кода java во временном файле с соответствующими пакетами и переменными.

Если то, о чем я говорю, полезно в какой-то мере, я рад помочь вам поделиться более подробной информацией о моих решениях.

тенистый алаа
источник