Вызов Java из Python

Каков наилучший способ вызова 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 - это мертвый проект?

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

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

9 ответов

Решение

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

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

Краткий ответ: Jpype работает довольно хорошо и проверен во многих проектах (таких как python-кипарис), но Pyjnius быстрее и проще, чем JPype

Я пробовал Pyjnius/Jnius, JCC, Javabridge, Jpype и Py4j.

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

Вы также можете использовать 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 VM, которую вы хотите вызвать.

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

Отказ от ответственности: я автор Py4J

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

Я на OSX 10.10.2, и мне удалось использовать JPype.

Я столкнулся с проблемами при установке с Jnius ( другие тоже), Javabridge установил, но при попытке использовать его у меня возникли загадочные ошибки, у PyJ4 возникло неудобство, связанное с необходимостью сначала запустить сервер Gateway на 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
...

Если вы находитесь в 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()

В последнее время я много чего интегрировал в Python, включая Java. Самый надежный метод, который я нашел, - это использование IKVM и оболочки C#.

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

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

Теперь вы можете создать некоторые заглушки-обертки, которые вызывают методы, которые вы хотите предоставить, и пометить эти методы как DllEport. См. /questions/39226908/vyizov-biblioteki-c-iz-python/39226927#39226927 для получения подробной информации.

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

Я пробовал это с Python 2.7, но он должен работать и с 3.0. Работает на Windows и Linux

Если вам случается использовать C#, то это, вероятно, лучший подход для интеграции практически всего в Python.

Я только начинаю использовать JPype 0.5.4.2 (июль 2011), и похоже, что он работает хорошо...
Я на Xubuntu 10.04

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

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

Благодаря моему собственному опыту, когда я пытался запустить некоторый Java-код из Python, подобно тому, как Python-код работает в Java-коде в Python, я не смог найти простую методологию.

Мое решение моей проблемы состояло в том, чтобы запустить этот Java-код в виде скриптов BeanShell, вызвав интерпретатор BeanShell как комнаду оболочки из моего кода Python после редактирования Java-кода во временном файле с соответствующими пакетами и переменными.

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

Другие вопросы по тегам