Различные / лучшие подходы для вызова функции Python из Java
Я новичок в Python и пытаюсь вызвать функцию Python из Java.
Мои основные требования следующие:
- вызов должен быть прозрачным, в том смысле, что он не должен требовать изменения
.py
файл просто, чтобы позволить ему быть вызванным из Java. Мне может быть предоставлен любой файл Python с некоторыми функциями внутри него. Я должен иметь возможность вызывать любую из этих функций без необходимости изменения.py
файл. - Я хочу иметь возможность отправлять аргументы обоих примитивных типов (
int
,String
,floats
и т. д.) или не примитивные типы (HashMap
,ArrayList
) из Java в функцию Python и получить обратно возвращенный объект (который может быть примитивных типов или не примитивных типов) из Python в Java. Я также использую pandas DataFrame и numpy ndarray и, следовательно, также хочу иметь возможность отправлять и получать соответствующие объекты в и из Java. - Я предпочитаю придерживаться CPython вместо Jython, потому что мне может потребоваться использовать более новые библиотеки, которые могут быть недоступны в Jython.
Есть несколько вариантов, которые я нашел в Интернете. Мало кто из них:
Используйте PythonInterpreter Jython, с помощью которого я могу вызвать функцию Python, не требуя каких-либо изменений в
.py
файл сценария:py1.py
def square2(list): squares = [] for i in list: squares.append(i*i) return squares
JythonTest.groovy
import org.python.util.PythonInterpreter import org.python.core.*; class JythonTest { static main(def args) { PythonInterpreter pi = new PythonInterpreter() pi.exec("from py1 import square2") PyFunction pf = (PyFunction)pi.get("square2") println pf.__call__(new PyList([1,2,3,4]))[2] //9 } }
Я очень хорошо могу удовлетворить свои потребности. Но это не CPython.
Использовать ScriptEngine: это очень похоже на PythonInterpreter. Но опять же его Jython. Кроме того, в отличие от PythonInterpreter, мы не можем работать с Jython 2.5+ и не можем напрямую обращаться к PyObjects. Так что эта опция может быть очень хорошо закрыта.
- Используйте py4j: пример поиска Cant, который минимален, как в случае с Jython PythonInterpreter
- Используйте java2python. Но не так много информации о вызове python из java, чтобы я мог сделать вывод, могут ли мои вышеуказанные требования быть выполнены. Кто-нибудь может пролить больше света на это? Точнее, если мы сможем написать такой же минимальный код, как в Jython PythonInterpreter.
- Используйте JPype: Однако после быстрого прохождения я чувствую, что не смогу написать столь же минимальный код, как в случае Jython PythonInterpreter. Также я почувствовал, что проект несколько не в разработке. Это?
Кажется, что Jython PythonInterpreter - лучший выбор, если я правильно понял все вышеперечисленные подходы. Я сделал ошибки, схватив их? Также есть какой-нибудь другой лучший вариант?
2 ответа
На данный момент нет ответа на эту проблему. Использование CPython зависит от выполнения байт-кодов Python, что, в свою очередь, требует, чтобы интерпретатор Python был встроен в среду выполнения. Поскольку ни одна среда исполнения Java не поставляется со встроенным интерпретатором Python, он действительно выглядит так, как будто Jython - лучший ответ.
Иногда нужный вам ответ просто не доступен!
@Mahesha999, относительно способности придерживаться CPython, что кажется важным сейчас с вашего последнего комментария:
Jep - это хороший вариант, чтобы иметь возможность запускать код Python, который использует вызовы native, например, панд, о которых вы упоминали.
Вам нужно написать некоторый код переноса, потому что Jep реализует только автоматическое преобразование между Java и Python между наиболее используемыми типами, которые pandas.DataFrame
не является.
Однако, если ваш вариант использования не сложный, вы можете получить доступ к объектам Pandas как numpy.NDArray
возражать DataFrame.values
на вашем экземпляре dataframe, и Jep реализует преобразование в класс Java, который он встраивает для NDArray.
Вы можете вернуться к значениям Java из кода Python, который вы выполняете, используя Jep.getValue(String pythonVariableName, Class clazz)
Например
Jep jep = new Jep();
jep.eval("import my_script");
jep.eval("df = my_script.function_returning_a_dataframe()");
jep.eval("col = df.a_column.value");
NDArray myCol = jep.getValue("col", NDArray.class);
Я делаю это в проекте, который я написал в Python, и который мне нужно интегрировать как плагин в приложение Java, пока он работает.