Вызов Python на Java?

117

Мне интересно, можно ли вызывать функции python из java-кода с помощью jython или только для вызова java-кода из python?

Шахаб
источник
3
Пожалуйста, посмотрите на аналогичный вопрос и прочтите ответ. bytes.com/topic/python/answers/…
AlexR

Ответы:

101

Jython: Python для платформы Java - http://www.jython.org/index.html

Вы можете легко вызывать функции Python из кода Java с помощью Jython. Это до тех пор, пока ваш код Python работает под jython, т.е. не использует некоторые c-расширения, которые не поддерживаются.

Если это сработает для вас, это, безусловно, самое простое решение, которое вы можете получить. В противном случае вы можете использовать org.python.util.PythonInterpreterновую поддержку интерпретатора Java6.

Простой пример из моей головы - но я надеюсь, он сработает: (для краткости проверка ошибок не выполняется)

PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("import sys\nsys.path.append('pathToModules if they are not there by default')\nimport yourModule");
// execute a function that takes a string and returns a string
PyObject someFunc = interpreter.get("funcName");
PyObject result = someFunc.__call__(new PyString("Test!"));
String realResult = (String) result.__tojava__(String.class);
Voo
источник
Я установил JYthon, или я предполагаю, что установил, и продолжаю пытаться запустить код, который вы обрисовали в общих чертах, но он отмечен как ошибка. Нужно ли для установки Jython переходить в определенную папку в папках python или java?
Shahab
2
Ошибок нет, мне просто сложно интегрировать Jython в Netbeans
Шахаб
Если ошибки нет, это сработает, так что это, очевидно, не тот случай;) «Ошибка» не означает ошибку времени выполнения, также может быть ошибкой компиляции.
Voo
Мое плохое, это было неправильное употребление этого слова. Я пытался добавить jython.jar в свой проект и netbeans. Но я понял это
Шахаб
1
Срок действия Python 2 - 1.1.2020, а Jython поддерживает только Python 2.7. так что ни один Jython не мертв. Лучший (самый простой) вариант - Jep lib
garyee
63

Эй, я думал, что введу свой ответ на этот вопрос, хотя уже поздно. Я думаю, что есть несколько важных моментов, которые следует учитывать в первую очередь, учитывая, насколько сильной вы хотите иметь связь между java и python.

Во-первых, вы хотите вызывать только функции или действительно хотите, чтобы код Python изменял данные в ваших java-объектах? Это очень важно. Если вы хотите вызвать код Python с аргументами или без них, это не очень сложно. Если ваши аргументы примитивны, это еще более упрощает задачу. Однако, если вы хотите, чтобы java-класс реализовал функции-члены в python, которые изменяют данные java-объекта, то это не так просто и прямо.

Во-вторых , мы говорим о cpython или подойдет jython? Я бы сказал, что cpython - это то, что вам нужно! Я бы сказал, что именно поэтому питон такой крутой! Имея такие высокие абстракции, при необходимости, доступ к c, c ++. Представьте, если бы это было в java. Этот вопрос даже не стоит задавать, подходит ли jython, потому что тогда это все равно легко.

Итак, я поиграл со следующими методами и перечислил их от простого к сложному:

Java в Jython

Преимущества: Тривиально просто. Имеются актуальные ссылки на объекты Java

Недостатки: нет CPython, очень медленно!

Jython из java настолько прост, и если этого действительно достаточно, то отлично. Однако это очень медленно и без cpython! Стоит ли жить без cpython, я так не думаю! Вы можете легко получить код Python, реализующий ваши функции-члены для Java-объектов.

Из Java в Jython в CPython через Pyro

Pyro - это модуль удаленного объекта для Python. У вас есть объект в интерпретаторе cpython, и вы можете отправлять ему объекты, которые передаются через сериализацию, а также он может возвращать объекты через этот метод. Обратите внимание: если вы отправляете сериализованный объект python из jython, а затем вызываете некоторые функции, которые изменяют данные в его элементах, вы не увидите этих изменений в java. Вам просто нужно не забыть отправить обратно те данные, которые вы хотите от пиротехники. Я считаю, что это самый простой способ попасть на cpython! Вам не нужны ни jni, ни jna, ни swig, ни .... Вам не нужно знать ни c, ни c ++. круто, да?

Преимущества: доступ к cpython, не такой сложный, как следующие методы

Недостатки: невозможно изменить данные членов объектов Java непосредственно из Python. Отчасти косвенно (jython - средний человек).

Из Java в C / C ++ через JNI / JNA / SWIG в Python через встроенный интерпретатор (возможно, с использованием библиотек BOOST?)

Боже мой, этот метод не для слабонервных. И я могу вам сказать, что мне потребовалось очень много времени, чтобы добиться этого приличным методом. Основная причина, по которой вы хотели бы это сделать, заключается в том, чтобы вы могли запускать код cpython, который полностью контролирует ваш объект java. Есть несколько важных моментов, которые следует учитывать, прежде чем принимать решение об использовании java (который похож на шимпанзе) с питоном (который похож на лошадь). Во-первых, если вы сломаете интерпретатор, это отключит вашу программу! И не заставляйте меня начинать с вопросов параллелизма! Кроме того, есть выделенный участок котла, я считаю, что нашел лучшую конфигурацию, чтобы минимизировать этот котел, но все же он выделен! Итак, как это сделать: считайте, что C ++ - ваш посредник, а ваши объекты на самом деле являются объектами C ++! Хорошо, что ты это знаешь сейчас. Просто напишите свой объект, как если бы ваша программа как в cpp, а не в java, с данными, к которым вы хотите получить доступ из обоих миров. Затем вы можете использовать генератор оболочки под названием swig (http://www.swig.org/Doc1.3/Java.html ), чтобы сделать это доступным для java и скомпилировать dll, которую вы вызываете System.load (имя dll здесь) в java. Сначала сделайте это, а затем переходите к самому сложному! Чтобы добраться до Python, вам нужно встроить интерпретатор. Во - первых , я предлагаю делать некоторые программы интерпретатора привет или это учебник Встраивание питона в C / C . Как только вы это сделаете, самое время заставить лошадь и обезьяну танцевать! Вы можете отправить объект C ++ в Python через [boost] [3]. Я знаю, что не давал вам рыбу, я просто сказал вам, где найти рыбу. Некоторые указатели, которые следует учитывать при компиляции.

Когда вы компилируете boost, вам нужно будет скомпилировать общую библиотеку. И вам нужно включить и связать нужные вам материалы из jdk, например jawt.lib, jvm.lib (вам также понадобится клиент jvm.dll на вашем пути при запуске приложения), а также python27.lib или что угодно и boost_python-vc100-mt-1_55.lib. Затем включите Python / include, jdk / include, boost и используйте только общие библиотеки (dll), иначе boost будет слезливым. И да, я знаю. Есть очень много способов, по которым это может испортиться. Поэтому убедитесь, что вы выполняете каждую вещь блок за блоком. Затем соедините их.

Snickers3192
источник
2
Вот библиотека, которая позволяет вам один раз написать ваши скрипты python и решить, какой метод интеграции (Jython, CPython через Jep и Py4j) использовать во время выполнения: github.com/subes/invesdwin-context-python Поскольку каждый метод имеет свои преимущества / недостатки
subes
@subes этот проект выглядит потрясающе. Я написал это недавно. Я призываю вас написать ответ, я бы за него проголосовал. Мне не нравится главный ответ, ха-ха, потому что я не думаю, что он предоставляет много полезной информации вне поиска Google.
Snickers3192
Я создал отдельный ответ
subes
3
этот ответ пахнет на «это должен быть принятый ответ» или это только у меня? ;-)
Маурисио Грасиа Гутьеррес
18

Неумно иметь код Python внутри java. Оберните свой код Python во флягу или другую веб-платформу, чтобы сделать его микросервисом. Сделайте вашу Java-программу способной вызывать этот микросервис (например, через REST).

Поверьте, это очень просто и избавит вас от множества проблем. Коды слабо связаны, поэтому их можно масштабировать.

Обновлено 24 марта 2020 г .: Согласно комментарию @stx, вышеуказанный подход не подходит для массовой передачи данных между клиентом и сервером. Вот еще один подход, который я рекомендовал: соединение Python и Java с Rust (C / C ++ тоже в порядке). https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0

Пеймин Ху
источник
+1, но как насчет дополнительной производительности и накладных расходов на связь, связанных с созданием и анализом двусторонних сообщений на обоих концах?
stx
да, для этого необходимо определить интерфейс api с минимальным требуемым вводом / выводом. Неразумно передавать много данных между клиентом и сервером в сети. Если вы не можете определить такой интерфейс, то такой подход к дизайну не подходит.
Пеймин Ху,
10

В некоторых ответах упоминается, что вы можете использовать JNI или JNA для доступа к cpython, но я бы не рекомендовал начинать с нуля, потому что уже есть библиотеки с открытым исходным кодом для доступа к cpython из java. Например:

bsteffen
источник
8

Вот библиотека, которая позволяет вам один раз написать ваши скрипты на Python и решить, какой метод интеграции (Jython, CPython / PyPy через Jep и Py4j) использовать во время выполнения:

https://github.com/subes/invesdwin-context-python

Поскольку у каждого метода есть свои преимущества / недостатки, как описано в ссылке.

subes
источник
У этого проекта нет релизов.
Кристиан
@ChristianSchlichtherle invesdwin-context-python версии 1.0.0 недоступен; благодаря этой маленькой жемчужине: github.com/loewenfels/dep-graph-releaser
subes
6

Это зависит от того, что вы подразумеваете под функциями Python? если они были написаны на cpython, вы не можете напрямую вызывать их, вам придется использовать JNI , но если они были написаны на Jython, вы можете легко вызвать их из java, поскольку jython в конечном итоге генерирует байтовый код java.

Теперь, когда я говорю, что написано на cpython или jython, это не имеет особого смысла, потому что python - это python, и большая часть кода будет работать в обеих реализациях, если вы не используете определенные библиотеки, которые полагаются на cpython или java.

см. здесь, как использовать интерпретатор Python в Java.

Анураг Униял
источник
5

В зависимости от ваших требований могут быть полезны такие параметры, как XML-RPC , которые можно использовать для удаленного вызова функций практически на любом языке, поддерживающем протокол.

Timo
источник
5

GraalVM - хороший выбор. Я сделал комбинацию Java + Javascript с GraalVM для дизайна микросервисов (Java с отражением Javascript). Недавно они добавили поддержку python, я бы попробовал, особенно с учетом того, насколько большим стало его сообщество за эти годы.

Wildhammer
источник
4

Вы можете вызывать любой язык из Java, используя собственный интерфейс Java

nidhin
источник
6
Любой язык, который сам может быть вызван из c, то есть. Ну ладно, python может, но Jython - гораздо более простое решение (или использование PyInterpreter в j6 +). Не так уж и тривиально написать код для вызова функций Python из c.
Voo
2

У Jython есть некоторые ограничения:

Есть ряд отличий. Во-первых, программы Jython не могут использовать модули расширения CPython, написанные на C. Эти модули обычно имеют файлы с расширением .so, .pyd или .dll. Если вы хотите использовать такой модуль, вам следует поискать эквивалент, написанный на чистом Python или Java. Хотя технически возможно поддерживать такие расширения - IronPython делает это - в Jython это не планируется.

Распространять мои сценарии Python в виде файлов JAR с помощью Jython?

вы можете просто вызвать скрипты Python (или скрипты bash или Perl) из Java с помощью Runtime или ProcessBuilder и передать вывод обратно в Java:

Запуск сценария оболочки bash на java

Запуск командной строки в Java

java runtime.getruntime () получение вывода от выполнения программы командной строки

Алекс
источник
0

Это дает неплохой обзор текущих опций. Некоторые из них указаны в других ответах. Jython нельзя использовать, пока они не решат реализовать Python 3.x, а многие другие проекты создаются на стороне Python и хотят получить доступ к java. Но есть еще несколько вариантов, чтобы назвать то, что еще не было названо: gRPC

garyee
источник