Вызов 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-кода во временном файле с соответствующими пакетами и переменными.
Если то, о чем я говорю, поможет вам в любом случае, я рад помочь вам поделиться более подробной информацией о моих решениях.