Вопрос-ответ

Calling Python in Java?

Вызов Python в Java?

Мне интересно, возможно ли вызывать функции Python из кода Java с помощью Jython, или это только для вызова кода Java из Python?

Переведено автоматически
Ответ 1

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);

По состоянию на 2021 год Jython не поддерживает Python 3.x

Ответ 2

Я думаю, что сначала следует рассмотреть несколько важных моментов, связанных с тем, насколько сильной вы хотите иметь связь между Java и Python.

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

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

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

Переход с Java на Jython

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

Недостатки: Нет CPython, чрезвычайно медленный!

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

С Java на Jython на CPython через Pyro

Pyro - это модуль удаленного объекта для Python. У вас есть некоторый объект в интерпретаторе CPython, и вы можете отправлять ему объекты, которые передаются посредством сериализации, и он также может возвращать объекты с помощью этого метода. Обратите внимание, что если вы отправляете сериализованный объект Python из Jython, а затем вызываете некоторые функции, которые изменяют данные в его элементах, то вы не увидите этих изменений в Java. Вам просто нужно не забыть отправить обратно данные, которые вы хотите получить из Pyro. Я считаю, что это самый простой способ добраться до CPython! Вам не нужен ни JNI, ни JNA, ни SWIG, ни.... Вам не нужно знать ни C, ни C ++. Круто, да?

Преимущества:


  • Доступ к CPython

  • Не так сложно, как следующие методы

Недостатки:


  • Невозможно изменить данные-члены объектов Java непосредственно из Python

  • Несколько косвенный (Jython - посредник)

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

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

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

Ответ 3

Неразумно иметь код python внутри java. Оберните свой код python с помощью flask или другого веб-фреймворка, чтобы сделать его микросервисом. Это позволяет вашей программе 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

Ответ 4

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

2023-09-27 12:31 java